From b4a7b52f3044ebc51b4529cfcd46682815f69545 Mon Sep 17 00:00:00 2001
From: Graham Dobbins
Date: Tue, 28 Mar 2017 07:48:58 -0400
Subject: [PATCH] * src/editfns.c (styled_format): Add %'d format specifier
---
etc/NEWS | 5 +++++
src/editfns.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 70 insertions(+), 2 deletions(-)
diff --git a/etc/NEWS b/etc/NEWS
index cd98f53399..da593b81d8 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1055,6 +1055,11 @@ its window gets deleted by 'delete-other-windows'.
*** New command 'window-swap-states' swaps the states of two live
windows.
+---
+*** 'format' now accepts the specifier "%'d" to format integers into
+groups of size 'format-digit-grouping' with separator
+'format-digit-separator' which default to 3 and comma respectively.
+
* Changes in Emacs 26.1 on Non-Free Operating Systems
diff --git a/src/editfns.c b/src/editfns.c
index 65c0c721d1..b6e8c489c0 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -3884,7 +3884,7 @@ specifiers, as follows:
%character
-where flags is [+ #-0]+, width is [0-9]+, and precision is a literal
+where flags is [+ #-0\\=']+, width is [0-9]+, and precision is a literal
period "." followed by [0-9]+
The + flag character inserts a + before any positive number, while a
@@ -3900,6 +3900,10 @@ the precision is zero; for %g, it causes a decimal point to be
included even if the the precision is zero, and also forces trailing
zeros after the decimal point to be left in place.
+The \\=' flag is ignored for all arguments except %d. If the argument
+is an integer it is printed in groupings whose size is dictated by
+`format-digit-grouping' and are separated by `format-digit-separator'.
+
The width specifier supplies a lower limit for the length of the
printed representation. The padding, if any, normally goes on the
left, but it goes on the right if the - flag is present. The padding
@@ -4059,6 +4063,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
bool space_flag = false;
bool sharp_flag = false;
bool zero_flag = false;
+ bool apos_flag = false;
for (; ; format++)
{
@@ -4069,6 +4074,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
case ' ': space_flag = true; continue;
case '#': sharp_flag = true; continue;
case '0': zero_flag = true; continue;
+ case '\'': apos_flag = true; continue;
}
break;
}
@@ -4381,6 +4387,49 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
}
}
sprintf_bytes = sprintf (sprintf_buf, convspec, prec, x);
+
+ if (apos_flag && INTEGERP (args[n]))
+ {
+ Lisp_Object real_grouping = Vformat_digit_grouping;
+ EMACS_INT grouping;
+ if (CONSP (real_grouping))
+ {
+ CHECK_RANGED_INTEGER (XCAR (real_grouping), \
+ 1, MOST_POSITIVE_FIXNUM);
+ grouping = XINT (XCAR (real_grouping));
+ }
+ else
+ {
+ CHECK_RANGED_INTEGER (real_grouping, \
+ 1, MOST_POSITIVE_FIXNUM);
+ grouping = XINT (real_grouping);
+ }
+
+ CHECK_CHARACTER (Vformat_digit_separator);
+
+ char last_char;
+ char temp_char;
+ for (ptrdiff_t i = sprintf_bytes - grouping; \
+ i > 0; i -= grouping)
+ {
+ last_char = XFASTINT (Vformat_digit_separator);
+ for (ptrdiff_t j = i; j <= sprintf_bytes; j++)
+ {
+ temp_char = sprintf_buf[j];
+ sprintf_buf[j] = last_char;
+ last_char = temp_char;
+ }
+ sprintf_bytes++;
+ if (CONSP (real_grouping) \
+ && !NILP (XCDR (real_grouping)))
+ {
+ real_grouping = XCDR (real_grouping);
+ CHECK_RANGED_INTEGER (XCAR (real_grouping), \
+ 1, MOST_POSITIVE_FIXNUM);
+ grouping = XINT (XCAR (real_grouping));
+ }
+ }
+ }
}
else
{
@@ -5171,7 +5220,21 @@ functions if all the text being accessed has this property. */);
DEFVAR_LISP ("operating-system-release", Voperating_system_release,
doc: /* The release of the operating system Emacs is running on. */);
- defsubr (&Spropertize);
+ DEFVAR_LISP ("format-digit-grouping",
+ Vformat_digit_grouping,
+ doc: /* Number of digits in each group of a formatted
+number in `format'. If a list, the first number applies to the least
+significant grouping and so on, with the last number applying to all
+remaining groupings. */);
+ Vformat_digit_grouping = make_number (3);
+
+ DEFVAR_LISP ("format-digit-separator",
+ Vformat_digit_separator,
+ doc: /* Character to use as grouping separator for
+formatted numbers in `format'. */);
+ Vformat_digit_separator = make_number (',');
+
+ defsubr (&Spropertize);
defsubr (&Schar_equal);
defsubr (&Sgoto_char);
defsubr (&Sstring_to_char);
--
2.12.1