unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Gdobbins <gdobbins@protonmail.com>
To: Paul Eggert <eggert@cs.ucla.edu>
Cc: emacs-devel@gnu.org
Subject: Re: RFC: locale-sensitive Emacs functions
Date: Tue, 28 Mar 2017 07:59:25 -0400	[thread overview]
Message-ID: <DUkEbNKVK1611uZJHQLMjX4QQRzby0Sg5dlDxNIC9xN1Xp_3ujOAi5g4L6azht5tKDB1qpql6BokG-QJoixg_VYpVFXX3HTa6fwTV3orFeI=@protonmail.com> (raw)
In-Reply-To: <721338e4-fad3-e33c-2a77-59107fbe1ff2@cs.ucla.edu>


[-- Attachment #1.1: Type: text/plain, Size: 1350 bytes --]

>I remember concluding that I was glad I didn't have to write code to support the '
>flag, as it would require messing with the LC_NUMERIC locale setting (currently
>hardwired to "C" for other good reasons) and would make for some work redoing
>carefully-calculated output buffer sizes internal to 'format', not to mention
>the character set conversion that would be required.

The way I've proposed should obviate those problems. Since the variables governing the behavior are set by the user, LC_NUMERIC need not be consulted. If it is deemed necessary a function like set-locale-dependent-vars could be created to set these (and potentially other) variables, and the user could put it in their init if they so choose.

>For what it's worth, the Common Lisp approach cannot handle the Indian numbering
>system, which has a comma every two digits except that the last grouping
>contains three digits (e.g., "12,34,56,789").

The literal CL approach can't handle it, but it can be adapted to do so. The attached patch makes it so the format-digit-grouping variable can be a list. The first element of the list controls the grouping size of the least significant figures etc. until the last element controls all remaining groups. Using your example:

(let ((format-digit-grouping '(3 2)))
(format "%'d" 123456789)) => "12,34,56,789"

-- Graham Dobbins

[-- Attachment #1.2: Type: text/html, Size: 1823 bytes --]

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-src-editfns.c-styled_format-Add-d-format-specifier.patch --]
[-- Type: text/x-patch; name="0001-src-editfns.c-styled_format-Add-d-format-specifier.patch", Size: 4933 bytes --]

From b4a7b52f3044ebc51b4529cfcd46682815f69545 Mon Sep 17 00:00:00 2001
From: Graham Dobbins <gdobbins@protonmail.com>
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.
+
 \f
 * 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:
 
   %<flags><width><precision>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


  reply	other threads:[~2017-03-28 11:59 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-28  3:06 RFC: locale-sensitive Emacs functions Ted Zlatanov
2017-03-28  4:10 ` Gdobbins
2017-03-28  4:37   ` Paul Eggert
2017-03-28 11:59     ` Gdobbins [this message]
2017-03-28 12:45       ` Ted Zlatanov
2017-03-30 18:27         ` Ted Zlatanov
2017-03-31  4:27           ` Gdobbins
2017-03-31 17:59             ` Davis Herring
2017-03-28 19:37       ` Paul Eggert

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='DUkEbNKVK1611uZJHQLMjX4QQRzby0Sg5dlDxNIC9xN1Xp_3ujOAi5g4L6azht5tKDB1qpql6BokG-QJoixg_VYpVFXX3HTa6fwTV3orFeI=@protonmail.com' \
    --to=gdobbins@protonmail.com \
    --cc=eggert@cs.ucla.edu \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).