]> git.eshelyaron.com Git - emacs.git/commitdiff
New variable integer-output-format to print integers as characters (bug#44155)
authorJuri Linkov <juri@linkov.net>
Sat, 31 Oct 2020 20:11:02 +0000 (22:11 +0200)
committerJuri Linkov <juri@linkov.net>
Sat, 31 Oct 2020 20:11:02 +0000 (22:11 +0200)
* doc/lispref/streams.texi (Output Variables): Add integer-output-format.

* src/print.c (print_object): In case of Lisp_Int, print integers
as characters when Vinteger_output_format is Qt, and in hex format
when Vinteger_output_format is 16.
(Vinteger_output_format): New variable.

* test/src/print-tests.el (print-integer-output-format): New test.

doc/lispref/streams.texi
etc/NEWS
src/print.c
test/src/print-tests.el

index 2cd61ad04fc07f8a14ebbd07987598b3e77c1c27..f171f1377904c1dfbe98a563236f7007d52dd061 100644 (file)
@@ -902,3 +902,11 @@ variable.  The string should hold a @samp{%}-specification to be used
 in the C function @code{sprintf}.  For further restrictions on what
 you can use, see the variable's documentation string.
 @end defvar
+
+@defvar integer-output-format
+This variable specifies how to print integer numbers.  The default is
+@code{nil}, meaning use the decimal format.  When bound to @code{t},
+print integers as characters when an integer represents a character
+(@pxref{Basic Char Syntax}).  When bound to the number @code{16},
+print non-negative integers in the hexadecimal format.
+@end defvar
index 62cc8141647a0af87d3a7a8bd4c22db4f21ff66a..5a646d2bb973f42e83941b7fa4a2c0d9f09938f7 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1669,6 +1669,12 @@ ledit.el, lmenu.el, lucid.el and old-whitespace.el.
 \f
 * Lisp Changes in Emacs 28.1
 
+** New variable 'integer-output-format' determines how to print integer values.
+When this variable is bound to the value 't', integers are printed by
+printing functions as characters when an integer represents a character.
+When bound to the number 16, non-negative integers are printed in the
+hexadecimal format.
+
 +++
 ** 'define-globalized-minor-mode' now takes a :predicate parameter.
 This can be used to control which major modes the minor mode should be
index 53aa353769ba9ab3bb5cf3873b4cee04c9fe2d5a..fa65a3cb268bec7b24f0d25cd8d5e6aa9dbff3b8 100644 (file)
@@ -1908,8 +1908,31 @@ 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);
+       int c;
+       intmax_t i;
+
+       if (EQ (Vinteger_output_format, Qt) && CHARACTERP (obj)
+           && (c = XFIXNUM (obj)))
+         {
+           printchar ('?', printcharfun);
+           if (escapeflag
+               && (c == ';' || c == '(' || c == ')' || c == '{' || c == '}'
+                   || c == '[' || c == ']' || c == '\"' || c == '\'' || c == '\\'))
+             printchar ('\\', printcharfun);
+           printchar (c, printcharfun);
+         }
+       else if (INTEGERP (Vinteger_output_format)
+                && integer_to_intmax (Vinteger_output_format, &i)
+                && i == 16 && !NILP (Fnatnump (obj)))
+         {
+           int len = sprintf (buf, "#x%"pI"x", (EMACS_UINT) XFIXNUM (obj));
+           strout (buf, len, len, printcharfun);
+         }
+       else
+         {
+           int len = sprintf (buf, "%"pI"d", XFIXNUM (obj));
+           strout (buf, len, len, printcharfun);
+         }
       }
       break;
 
@@ -2247,6 +2270,13 @@ A value of nil means to use the shortest notation
 that represents the number without losing information.  */);
   Vfloat_output_format = Qnil;
 
+  DEFVAR_LISP ("integer-output-format", Vinteger_output_format,
+              doc: /* The format used to print integers.
+When t, print characters from integers that represent a character.
+When a number 16, print non-negative integers in the hexadecimal format.
+Otherwise, by default print integers in the decimal format.  */);
+  Vinteger_output_format = Qnil;
+
   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'.  */);
index eb9572dbdf40c5ffc7ac2a1f1592670d9c28c14a..7b026b6b21f54dc548befbe71d17746db0508c4e 100644 (file)
@@ -383,5 +383,25 @@ otherwise, use a different charset."
       (let ((print-length 1))
         (format "%S" h))))))
 
+(print-tests--deftest print-integer-output-format ()
+  ;; Bug#44155.
+  (let ((integer-output-format t)
+        (syms (list ?? ?\; ?\( ?\) ?\{ ?\} ?\[ ?\] ?\" ?\' ?\\ ?Á)))
+    (should (equal (read (print-tests--prin1-to-string syms)) syms))
+    (should (equal (print-tests--prin1-to-string syms)
+                   (concat "(" (mapconcat #'prin1-char syms " ") ")"))))
+  (let ((integer-output-format t)
+        (syms (list -1 0 1 ?\120 4194175 4194176 (max-char) (1+ (max-char)))))
+    (should (equal (read (print-tests--prin1-to-string syms)) syms)))
+  (let ((integer-output-format 16)
+        (syms (list -1 0 1 most-positive-fixnum (1+ most-positive-fixnum))))
+    (should (equal (read (print-tests--prin1-to-string syms)) syms))
+    (should (equal (print-tests--prin1-to-string syms)
+                   (concat "(" (mapconcat
+                                (lambda (i)
+                                  (if (and (>= i 0) (<= i most-positive-fixnum))
+                                      (format "#x%x" i) (format "%d" i)))
+                                syms " ") ")")))))
+
 (provide 'print-tests)
 ;;; print-tests.el ends here