Skip to content

Commit 2950065

Browse files
committed
patch 8.2.3315: cannot use single quote in a float number for readability
Problem: Cannot use single quote in a float number for readability. Solution: Support single quotes like in numbers. (closes #8713)
1 parent 2673599 commit 2950065

7 files changed

Lines changed: 72 additions & 10 deletions

File tree

src/float.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
int
3030
string2float(
3131
char_u *text,
32-
float_T *value) // result stored here
32+
float_T *value, // result stored here
33+
int skip_quotes)
3334
{
3435
char *s = (char *)text;
3536
float_T f;
@@ -50,6 +51,32 @@ string2float(
5051
*value = NAN;
5152
return 3;
5253
}
54+
if (skip_quotes && vim_strchr((char_u *)s, '\'') != NULL)
55+
{
56+
char_u buf[100];
57+
char_u *p = buf;
58+
int quotes = 0;
59+
60+
vim_strncpy(buf, (char_u *)s, 99);
61+
p = buf;
62+
for (;;)
63+
{
64+
// remove single quotes between digits, not in the exponent
65+
if (*p == '\'')
66+
{
67+
++quotes;
68+
mch_memmove(p, p + 1, STRLEN(p));
69+
}
70+
if (!vim_isdigit(*p))
71+
break;
72+
p = skipdigits(p);
73+
}
74+
s = (char *)buf;
75+
f = strtod(s, &s);
76+
*value = f;
77+
return (int)((char_u *)s - buf) + quotes;
78+
}
79+
5380
f = strtod(s, &s);
5481
*value = f;
5582
return (int)((char_u *)s - text);
@@ -488,16 +515,19 @@ f_str2float(typval_T *argvars, typval_T *rettv)
488515
{
489516
char_u *p;
490517
int isneg;
518+
int skip_quotes;
491519

492520
if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
493521
return;
494522

523+
skip_quotes = argvars[1].v_type != VAR_UNKNOWN && tv_get_bool(&argvars[1]);
524+
495525
p = skipwhite(tv_get_string_strict(&argvars[0]));
496526
isneg = (*p == '-');
497527

498528
if (*p == '+' || *p == '-')
499529
p = skipwhite(p + 1);
500-
(void)string2float(p, &rettv->vval.v_float);
530+
(void)string2float(p, &rettv->vval.v_float, skip_quotes);
501531
if (isneg)
502532
rettv->vval.v_float *= -1;
503533
rettv->v_type = VAR_FLOAT;

src/json.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -791,12 +791,13 @@ json_decode_item(js_read_T *reader, typval_T *res, int options)
791791
{
792792
float_T f;
793793

794-
len = string2float(p, &f);
794+
len = string2float(p, &f, FALSE);
795795
}
796796
else
797797
{
798798
cur_item->v_type = VAR_FLOAT;
799-
len = string2float(p, &cur_item->vval.v_float);
799+
len = string2float(p, &cur_item->vval.v_float,
800+
FALSE);
800801
}
801802
}
802803
else

src/proto/float.pro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* float.c */
2-
int string2float(char_u *text, float_T *value);
2+
int string2float(char_u *text, float_T *value, int skip_quotes);
33
void f_abs(typval_T *argvars, typval_T *rettv);
44
void f_acos(typval_T *argvars, typval_T *rettv);
55
void f_asin(typval_T *argvars, typval_T *rettv);

src/testdir/test_float_func.vim

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,28 @@ func Test_str2float()
239239
call assert_equal('nan', string(str2float('NaN')))
240240
call assert_equal('nan', string(str2float(' nan ')))
241241

242-
call assert_equal(1.2, str2float(1.2))
242+
call assert_equal('123456.789', string(str2float("123'456.789", 1)))
243+
call assert_equal('123456.789', string(str2float("12'34'56.789", 1)))
244+
call assert_equal('123456.789', string(str2float("1'2'3'4'5'6.789", 1)))
245+
call assert_equal('1.0', string(str2float("1''2.3", 1)))
246+
call assert_equal('123456.7', string(str2float("123'456.7'89", 1)))
247+
248+
call assert_equal(1.2, str2float(1.2, 0))
243249
call CheckDefAndScriptFailure2(['str2float(1.2)'], 'E1013: Argument 1: type mismatch, expected string but got float', 'E1174: String required for argument 1')
244250
call assert_fails("call str2float([])", 'E730:')
245251
call assert_fails("call str2float({})", 'E731:')
246252
call assert_fails("call str2float(function('string'))", 'E729:')
247253
endfunc
248254

255+
def Test_float_quotes()
256+
call assert_equal('123456.789', string(123'456.789))
257+
call assert_equal('123456.789', string(12'34'56.789))
258+
call assert_equal('123456.789', string(1'2'3'4'5'6.789))
259+
260+
call assert_fails("echo string(1''2.3)", 'E116:')
261+
call assert_fails("echo string(123'456.7'89)", 'E116:')
262+
enddef
263+
249264
func Test_float2nr()
250265
call assert_equal(1, float2nr(1.234))
251266
call assert_equal(123, float2nr(1.234e2))

src/typval.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1704,6 +1704,7 @@ eval_number(
17041704
int want_string UNUSED)
17051705
{
17061706
int len;
1707+
int skip_quotes = current_sctx.sc_version >= 4;
17071708
#ifdef FEAT_FLOAT
17081709
char_u *p;
17091710
int get_float = FALSE;
@@ -1718,7 +1719,20 @@ eval_number(
17181719
if (**arg == '.')
17191720
p = *arg;
17201721
else
1721-
p = skipdigits(*arg + 1);
1722+
{
1723+
p = *arg + 1;
1724+
if (skip_quotes)
1725+
for (;;)
1726+
{
1727+
if (*p == '\'')
1728+
++p;
1729+
if (!vim_isdigit(*p))
1730+
break;
1731+
p = skipdigits(p);
1732+
}
1733+
else
1734+
p = skipdigits(p);
1735+
}
17221736
if (!want_string && p[0] == '.' && vim_isdigit(p[1]))
17231737
{
17241738
get_float = TRUE;
@@ -1740,7 +1754,7 @@ eval_number(
17401754
{
17411755
float_T f;
17421756

1743-
*arg += string2float(*arg, &f);
1757+
*arg += string2float(*arg, &f, skip_quotes);
17441758
if (evaluate)
17451759
{
17461760
rettv->v_type = VAR_FLOAT;
@@ -1784,7 +1798,7 @@ eval_number(
17841798
varnumber_T n;
17851799

17861800
// decimal, hex or octal number
1787-
vim_str2nr(*arg, NULL, &len, current_sctx.sc_version >= 4
1801+
vim_str2nr(*arg, NULL, &len, skip_quotes
17881802
? STR2NR_NO_OCT + STR2NR_QUOTE
17891803
: STR2NR_ALL, &n, NULL, 0, TRUE);
17901804
if (len == 0)

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,8 @@ static char *(features[]) =
755755

756756
static int included_patches[] =
757757
{ /* Add new patch number below this line */
758+
/**/
759+
3315,
758760
/**/
759761
3314,
760762
/**/

src/viminfo.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1247,7 +1247,7 @@ read_viminfo_varlist(vir_T *virp, int writing)
12471247
(int)(tab - virp->vir_line + 1), TRUE);
12481248
#ifdef FEAT_FLOAT
12491249
else if (type == VAR_FLOAT)
1250-
(void)string2float(tab + 1, &tv.vval.v_float);
1250+
(void)string2float(tab + 1, &tv.vval.v_float, FALSE);
12511251
#endif
12521252
else
12531253
{

0 commit comments

Comments
 (0)