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