read-print: Guess the base to use for integers being printed.

Fixes <https://issues.guix.gnu.org/57090>.
Reported by Christopher Rodriguez <yewscion@gmail.com>.

* guix/read-print.scm (%symbols-followed-by-octal-integers)
(%symbols-followed-by-hexadecimal-integers): New variables.
* guix/read-print.scm (integer->string): New procedure.
(pretty-print-with-comments): Use it.
* tests/read-print.scm: Add test.
This commit is contained in:
Ludovic Courtès 2022-09-01 15:54:08 +02:00
parent 8cf7997d7c
commit c3b1cfe76b
No known key found for this signature in database
GPG key ID: 090B11993D9AEBB5
2 changed files with 43 additions and 3 deletions

View file

@ -22,6 +22,7 @@ (define-module (guix read-print)
#:use-module (ice-9 rdelim)
#:use-module (ice-9 vlist)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-26)
#:use-module (srfi srfi-34)
#:use-module (srfi srfi-35)
#:use-module (guix i18n)
@ -426,6 +427,34 @@ (define (print-multi-line-comment str indent port)
(display (make-string indent #\space) port)
(loop tail)))))
(define %symbols-followed-by-octal-integers
;; Symbols for which the following integer must be printed as octal.
'(chmod umask mkdir mkstemp))
(define %symbols-followed-by-hexadecimal-integers
;; Likewise, for hexadecimal integers.
'(logand logior logxor lognot))
(define (integer->string integer context)
"Render INTEGER as a string using a base suitable based on CONTEXT."
(define base
(match context
((head . tail)
(cond ((memq head %symbols-followed-by-octal-integers) 8)
((memq head %symbols-followed-by-hexadecimal-integers)
(if (any (cut memq <> %symbols-followed-by-octal-integers)
tail)
8
16))
(else 10)))
(_ 10)))
(string-append (match base
(10 "")
(16 "#x")
(8 "#o"))
(number->string integer base)))
(define* (pretty-print-with-comments port obj
#:key
(format-comment
@ -661,9 +690,12 @@ (define new-column
(display ")" port)
(+ column 1)))))
(_
(let* ((str (if (string? obj)
(escaped-string obj)
(object->string obj)))
(let* ((str (cond ((string? obj)
(escaped-string obj))
((integer? obj)
(integer->string obj context))
(else
(object->string obj))))
(len (string-width str)))
(if (and (> (+ column 1 len) max-width)
(not delimited?))

View file

@ -247,6 +247,14 @@ (define-syntax-rule (test-pretty-print/sequence str args ...)
(+ a b))))
(list x y z))")
(test-pretty-print "\
(begin
(chmod \"foo\" #o750)
(chmod port
(logand #o644
(lognot (umask))))
(logand #x7f xyz))")
(test-pretty-print "\
(substitute-keyword-arguments (package-arguments x)
((#:phases phases)