bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#44155: Print integers as characters


From: Juri Linkov
Subject: bug#44155: Print integers as characters
Date: Thu, 22 Oct 2020 23:56:21 +0300
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (x86_64-pc-linux-gnu)

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'.  */);

reply via email to

[Prev in Thread] Current Thread [Next in Thread]