Subject: bug#44155: closed (Re: bug#44155: Print integers as characters)

From: [email-masked] (GNU bug Tracking System)
Date: Fri, 06 Nov 2020 13:04:02 +0000

Your bug report

#44155: Print integers as characters

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
44155: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=44155
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#44155: Print integers as characters
From: Mattias Engdegård <[email-masked]>
To: Eli Zaretskii <[email-masked]>
Cc: [email-masked], Andreas Schwab <[email-masked]>, Juri Linkov <[email-masked]>
Date: Fri, 6 Nov 2020 14:02:59 +0100
List-Id: <debbugs-submit.debbugs.gnu.org>

4 nov. 2020 kl. 17.58 skrev Mattias Engdegård <[email-masked]>:

> The last patch was incorrect; here is the right one. Apologies for the confusion.

Pushed to master, since there wasn't much left to discuss. As usual, it can be modified or reverted as needed.

Subject: Print integers as characters
From: Juri Linkov <[email-masked]>
To: [email-masked]
Date: Thu, 22 Oct 2020 23:56:21 +0300
List-Id: <debbugs-submit.debbugs.gnu.org>

Tags: patch

[Creating a separate feature request from bug#43866]

>> Let-binding a new variable 'print-integers-as-chars' to t:
>> 
>> (let ((print-integers-as-chars t))
>>   (pp '(("'A" . [?Á])
>>         ("'E" . [?É])
>>         ("'I" . [?Í])
>>         ("'O" . [?Ó])
>>         ("'U" . [?Ú])
>>         ("'Y" . [?Ý]))
>>       (current-buffer)))
>> 
>> prints integers as characters:
>> 
>> (("'A" .  [?Á])
>>  ("'E" .  [?É])
>>  ("'I" .  [?Í])
>>  ("'O" .  [?Ó])
>>  ("'U" .  [?Ú])
>>  ("'Y" .  [?Ý]))
>> 
>> with this patch:
>
> The idea is fine, but I have a few comments about implementation:
>
>>      case_Lisp_Int:
>>        {
>> -	int len = sprintf (buf, "%"pI"d", XFIXNUM (obj));
>> -	strout (buf, len, len, printcharfun);
>> +        if (!NILP (Vprint_integers_as_chars) && CHARACTERP (obj))
>                       ^^^^^^^^^^^^^^^^^^^^^^^^
> If this is supposed to be a boolean variable, please use DEFVAR_BOOL,
> with all the consequences.

Fixed in the next patch.

>> +            int len = sprintf (buf, "%s", SDATA (call1 (intern ("prin1-char"), obj)));
>
> Do we really need to call Lisp?  I thought we were quite capable of
> printing characters from C, aren't we?

Thanks for the hint.  Now the patch uses only C functions.
(My initial idea was to use eval-expression-print-format as a base that has

    (let ((char-string
           (and (characterp value)
                (<= value eval-expression-print-maximum-character)
                (char-displayable-p value)
                (prin1-char value))))

but it seems only the condition 'characterp' is needed in C implementation.)

>> @@ -2247,6 +2255,10 @@ syms_of_print (void)
>>  that represents the number without losing information.  */);
>>    Vfloat_output_format = Qnil;
>>  
>> +  DEFVAR_LISP ("print-integers-as-chars", Vprint_integers_as_chars,
>> +	       doc: /* Print integers as characters.  */);
>> +  Vprint_integers_as_chars = Qnil;
>
> I wonder whether it wouldn't be cleaner to add another optional
> argument to prin1, and let it bind some internal variable so that
> print_object does this, instead  of exposing this knob to Lisp.
> Because print_object is used all over the place, and who knows what
> will this do to other callers?

The variable 'print-integers-as-chars' is modeled after many similar
variables that affect the prin1 output:

- print-escape-control-characters
- print-escape-newlines
- print-escape-nonascii
- print-escape-multibyte
- print-length
- print-level
- print-quoted
- print-circle
- float-output-format

But now this leads me to think that maybe the new variable should be
like 'float-output-format', so it could be named 'integer-output-format'
and support options for different integer formats:

- 'character': print integers as characters;
- 'decimal': the default format;
- 'binary': print integers as e.g. #b010101;
- 'octal': print integers as e.g. #o777;
- 'hex': print integers as e.g. #x00ff;

diff --git a/src/print.c b/src/print.c
index dca095f281..909c55efed 100644
--- a/src/print.c
+++ b/src/print.c
@@ -1908,8 +1908,16 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
     {
     case_Lisp_Int:
       {
-	int len = sprintf (buf, "%"pI"d", XFIXNUM (obj));
-	strout (buf, len, len, printcharfun);
+        if (print_integers_as_characters && CHARACTERP (obj))
+          {
+            printchar ('?', printcharfun);
+            print_string (CALLN (Fstring, obj), printcharfun);
+          }
+        else
+          {
+            int len = sprintf (buf, "%"pI"d", XFIXNUM (obj));
+            strout (buf, len, len, printcharfun);
+          }
       }
       break;
 
@@ -2247,6 +2255,10 @@ syms_of_print (void)
 that represents the number without losing information.  */);
   Vfloat_output_format = Qnil;
 
+  DEFVAR_BOOL ("print-integers-as-characters", print_integers_as_characters,
+	       doc: /* Print integers as characters.  */);
+  print_integers_as_characters = 0;
+
   DEFVAR_LISP ("print-length", Vprint_length,
 	       doc: /* Maximum length of list to print before abbreviating.
 A value of nil means no limit.  See also `eval-expression-print-length'.  */);