Subject: bug#77656: [PATCH] Don't escape "." in `prin1' unless followed by "?" or nothing

From: Spencer Baugh <[email-masked]>
Date: Tue, 15 Apr 2025 15:52:52 -0400

Stefan Monnier <[email-masked]> writes:

>> As for future Emacsen, I contend that we won't want to change how this
>> lexes in the future - it would break let-alist, for one thing.
>>
>> Incidentally, making it easier to work with let-alist was one of my main
>> motivations for this change, since it ubiquitously uses symbols which
>> start with ".".
>
> Thanks, it's good to have a clear use-case.  You might want to mention
> it in the commit message (tho at least now it's in the associated bug thread).

Sure, done in the attached revised patch.

> How often/much do we care about the printed form of `let-alist` expressions?

Not often, it's mostly just that it's more convenient when hacking on it
(as I was a while back to add numeric indexing), and I figured it was a
harmless change.

> Maybe limiting the effect to ". at the beginning of symbol doesn't need
> to be a escaped if the second char is a letter" would be good enough?

That sounds reasonable to me, done in the attached patch.

>From 6db264d4f8ab2a6f520591958263bf61e92f10cc Mon Sep 17 00:00:00 2001
From: Spencer Baugh <[email-masked]>
Date: Tue, 4 Jun 2024 10:35:10 -0400
Subject: [PATCH] Don't escape "." in `prin1' when followed by a letter

Among other users, let-alist widely uses symbols which start with a ".".
Make those symbols print more nicely by tweaking the escaping rules in
print_object to not escape a leading "." followed by a letter.  This is
a conservative change to avoid constraining future lexer changes.

This is a followup to 637dde4aba921435f78d0de769ad74c4f3230aa6, which
removed some unnecessary escaping of "." and "?" when printing symbols
in prin1.  (Actually, if we always escaped "?" (which was the case
before 637dde4aba92) then "." only ever needs to be escaped when
string_to_number returns non-nil.  So 637dde4aba92 could have just
dropped the escaping of "." with no other changes, if it didn't also
remove escaping of "?")

* src/print.c (print_object): Don't escape "." as the first
character in a symbol if followed by a letter. (bug#77656).
* test/src/print-tests.el (test-dots): Update for new behavior.
---
 src/print.c             | 9 ++++++---
 test/src/print-tests.el | 6 ++++--
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/print.c b/src/print.c
index c7cba5bface..b17ec337f70 100644
--- a/src/print.c
+++ b/src/print.c
@@ -2442,10 +2442,13 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
 	  ((c_isdigit (p[signedp]) || p[signedp] == '.')
 	   && !NILP (string_to_number (p, 10, &len))
 	   && len == size_byte)
-	  /* We don't escape "." or "?" (unless they're the first
-	     character in the symbol name).  */
+	  /* We don't escape "?" unless it's the first character in the
+	     symbol name.  */
 	  || *p == '?'
-	  || *p == '.';
+	  /* We don't escape "." unless it's the first character in the
+	     symbol name; even then, we don't escape it if it's followed
+	     by [a-zA-Z]. */
+	  || (*p == '.' && !(size_byte > 1 && c_isalpha (*(p+1))));
 
 	if (! NILP (Vprint_gensym)
 	    && !SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P (obj))
diff --git a/test/src/print-tests.el b/test/src/print-tests.el
index 1a04cf73f30..af57311135b 100644
--- a/test/src/print-tests.el
+++ b/test/src/print-tests.el
@@ -415,8 +415,10 @@ test-unreadable
 
 (ert-deftest test-dots ()
   (should (equal (prin1-to-string 'foo.bar) "foo.bar"))
-  (should (equal (prin1-to-string '.foo) "\\.foo"))
-  (should (equal (prin1-to-string '.foo.) "\\.foo."))
+  (should (equal (prin1-to-string '.foo) ".foo"))
+  (should (equal (prin1-to-string '.foo.) ".foo."))
+  (should (equal (prin1-to-string '.$) "\\.$"))
+  (should (equal (prin1-to-string '\.) "\\."))
   (should (equal (prin1-to-string 'bar?bar) "bar?bar"))
   (should (equal (prin1-to-string '\?bar) "\\?bar"))
   (should (equal (prin1-to-string '\?bar?) "\\?bar?")))
-- 
2.39.3