aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2022-01-03 11:04:40 +0100
committerLudovic Courtès <ludo@gnu.org>2022-01-10 14:59:18 +0100
commit6f892630ae4726297944fe34b3de4fb608caf66d (patch)
tree208d634c0fba6d4fb9b3fba06863998048e8c084
parent208a7aa17b101083bd9969fec9ca4e2dca37b3af (diff)
downloadguix-6f892630ae4726297944fe34b3de4fb608caf66d.tar.gz
guix-6f892630ae4726297944fe34b3de4fb608caf66d.zip
style: Add support for "newline forms".
This allows us to express cases where a newline should be inserted immediately after the head symbol of a list. * guix/scripts/style.scm (%newline-forms): New variable. (newline-form?): New procedure. (pretty-print-with-comments): Handle "newline forms". * tests/style.scm: Add test.
-rw-r--r--guix/scripts/style.scm43
-rw-r--r--tests/style.scm13
2 files changed, 50 insertions, 6 deletions
diff --git a/guix/scripts/style.scm b/guix/scripts/style.scm
index 625e942613..09c239498f 100644
--- a/guix/scripts/style.scm
+++ b/guix/scripts/style.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2021 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2021-2022 Ludovic Courtès <ludo@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
@@ -163,6 +163,19 @@
('with-output-to-file 2)
('with-input-from-file 2)))
+(define %newline-forms
+ ;; List heads that must be followed by a newline. The second argument is
+ ;; the context in which they must appear. This is similar to a special form
+ ;; of 1, except that indent is 1 instead of 2 columns.
+ (vhashq
+ ('arguments '(package))
+ ('sha256 '(origin source package))
+ ('base32 '(sha256 origin))
+ ('git-reference '(uri origin source))
+ ('search-paths '(package))
+ ('native-search-paths '(package))
+ ('search-path-specification '())))
+
(define (prefix? candidate lst)
"Return true if CANDIDATE is a prefix of LST."
(let loop ((candidate candidate)
@@ -188,6 +201,14 @@ surrounding SYMBOL."
(and (prefix? prefix context) (- level 1))))
alist))))
+(define (newline-form? symbol context)
+ "Return true if parenthesized expressions starting with SYMBOL must be
+followed by a newline."
+ (match (vhash-assq symbol %newline-forms)
+ (#f #f)
+ ((_ . prefix)
+ (prefix? prefix context))))
+
(define (escaped-string str)
"Return STR with backslashes and double quotes escaped. Everything else, in
particular newlines, is left as is."
@@ -377,6 +398,7 @@ Lists longer than LONG-LIST are written as one element per line."
(column (if overflow?
(+ indent 1)
(+ column (if delimited? 1 2))))
+ (newline? (newline-form? head context))
(context (cons head context)))
(if overflow?
(begin
@@ -384,17 +406,26 @@ Lists longer than LONG-LIST are written as one element per line."
(display (make-string indent #\space) port))
(unless delimited? (display " " port)))
(display "(" port)
+
(let* ((new-column (loop column column #t context head))
(indent (if (or (>= new-column max-width)
(not (symbol? head))
(sequence-would-protrude?
- (+ new-column 1) tail))
+ (+ new-column 1) tail)
+ newline?)
column
(+ new-column 1))))
- (define column
- (print-sequence context indent new-column tail #f))
- (display ")" port)
- (+ column 1))))
+ (when newline?
+ ;; Insert a newline right after HEAD.
+ (newline port)
+ (display (make-string indent #\space) port))
+
+ (let ((column
+ (print-sequence context indent
+ (if newline? indent new-column)
+ tail newline?)))
+ (display ")" port)
+ (+ column 1)))))
(_
(let* ((str (if (string? obj)
(escaped-string obj)
diff --git a/tests/style.scm b/tests/style.scm
index 6c449cb72e..8022688419 100644
--- a/tests/style.scm
+++ b/tests/style.scm
@@ -465,6 +465,19 @@ mnopqrstuvwxyz.\")"
;; Regular indentation for 'replace' here.
(replace \"gmp\" gmp))")
+(test-pretty-print "\
+(package
+ ;; Here 'sha256', 'base32', and 'arguments' must be
+ ;; immediately followed by a newline.
+ (source (origin
+ (method url-fetch)
+ (sha256
+ (base32
+ \"not a real base32 string\"))))
+ (arguments
+ '(#:phases %standard-phases
+ #:tests? #f)))")
+
(test-end)
;; Local Variables: