diff options
| -rw-r--r-- | guix/read-print.scm | 46 | ||||
| -rw-r--r-- | tests/read-print.scm | 22 |
2 files changed, 65 insertions, 3 deletions
diff --git a/guix/read-print.scm b/guix/read-print.scm index 2b626ba2811..33ed6e3dbe1 100644 --- a/guix/read-print.scm +++ b/guix/read-print.scm | |||
| @@ -35,6 +35,9 @@ | |||
| 35 | vertical-space-height | 35 | vertical-space-height |
| 36 | canonicalize-vertical-space | 36 | canonicalize-vertical-space |
| 37 | 37 | ||
| 38 | page-break | ||
| 39 | page-break? | ||
| 40 | |||
| 38 | comment | 41 | comment |
| 39 | comment? | 42 | comment? |
| 40 | comment->string | 43 | comment->string |
| @@ -83,6 +86,18 @@ | |||
| 83 | "Return a vertical space corresponding to a single blank line." | 86 | "Return a vertical space corresponding to a single blank line." |
| 84 | unit))) | 87 | unit))) |
| 85 | 88 | ||
| 89 | (define <page-break> | ||
| 90 | (make-record-type '<page-break> '() | ||
| 91 | #:parent <blank> | ||
| 92 | #:extensible? #f)) | ||
| 93 | |||
| 94 | (define page-break? (record-predicate <page-break>)) | ||
| 95 | (define page-break | ||
| 96 | (let ((break ((record-type-constructor <page-break>)))) | ||
| 97 | (lambda () | ||
| 98 | break))) | ||
| 99 | |||
| 100 | |||
| 86 | (define <comment> | 101 | (define <comment> |
| 87 | ;; Comments. | 102 | ;; Comments. |
| 88 | (make-record-type '<comment> '(str margin?) | 103 | (make-record-type '<comment> '(str margin?) |
| @@ -105,12 +120,17 @@ end with newline, otherwise an error is raised." | |||
| 105 | (&message (message "invalid comment string"))))) | 120 | (&message (message "invalid comment string"))))) |
| 106 | (string->comment str margin?)) | 121 | (string->comment str margin?)) |
| 107 | 122 | ||
| 123 | (define char-set:whitespace-sans-page-break | ||
| 124 | ;; White space, excluding #\page. | ||
| 125 | (char-set-difference char-set:whitespace (char-set #\page))) | ||
| 126 | |||
| 127 | (define (space? chr) | ||
| 128 | "Return true if CHR is white space, except for page breaks." | ||
| 129 | (char-set-contains? char-set:whitespace-sans-page-break chr)) | ||
| 130 | |||
| 108 | (define (read-vertical-space port) | 131 | (define (read-vertical-space port) |
| 109 | "Read from PORT until a non-vertical-space character is met, and return a | 132 | "Read from PORT until a non-vertical-space character is met, and return a |
| 110 | single <vertical-space> record." | 133 | single <vertical-space> record." |
| 111 | (define (space? chr) | ||
| 112 | (char-set-contains? char-set:whitespace chr)) | ||
| 113 | |||
| 114 | (let loop ((height 1)) | 134 | (let loop ((height 1)) |
| 115 | (match (read-char port) | 135 | (match (read-char port) |
| 116 | (#\newline (loop (+ 1 height))) | 136 | (#\newline (loop (+ 1 height))) |
| @@ -118,6 +138,15 @@ single <vertical-space> record." | |||
| 118 | ((? space?) (loop height)) | 138 | ((? space?) (loop height)) |
| 119 | (chr (unread-char chr port) (vertical-space height))))) | 139 | (chr (unread-char chr port) (vertical-space height))))) |
| 120 | 140 | ||
| 141 | (define (read-until-end-of-line port) | ||
| 142 | "Read white space from PORT until the end of line, included." | ||
| 143 | (let loop () | ||
| 144 | (match (read-char port) | ||
| 145 | (#\newline #t) | ||
| 146 | ((? eof-object?) #t) | ||
| 147 | ((? space?) (loop)) | ||
| 148 | (chr (unread-char chr port))))) | ||
| 149 | |||
| 121 | (define (read-with-comments port) | 150 | (define (read-with-comments port) |
| 122 | "Like 'read', but include <blank> objects when they're encountered." | 151 | "Like 'read', but include <blank> objects when they're encountered." |
| 123 | ;; Note: Instead of implementing this functionality in 'read' proper, which | 152 | ;; Note: Instead of implementing this functionality in 'read' proper, which |
| @@ -148,6 +177,11 @@ single <vertical-space> record." | |||
| 148 | (if blank-line? | 177 | (if blank-line? |
| 149 | (read-vertical-space port) | 178 | (read-vertical-space port) |
| 150 | (loop #t return))) | 179 | (loop #t return))) |
| 180 | ((eqv? chr #\page) | ||
| 181 | ;; Assume that a page break is on a line of its own and read | ||
| 182 | ;; subsequent white space and newline. | ||
| 183 | (read-until-end-of-line port) | ||
| 184 | (page-break)) | ||
| 151 | ((char-set-contains? char-set:whitespace chr) | 185 | ((char-set-contains? char-set:whitespace chr) |
| 152 | (loop blank-line? return)) | 186 | (loop blank-line? return)) |
| 153 | ((memv chr '(#\( #\[)) | 187 | ((memv chr '(#\( #\[)) |
| @@ -444,6 +478,12 @@ FORMAT-VERTICAL-SPACE; a useful value of 'canonicalize-vertical-space'." | |||
| 444 | (loop (- i 1)))) | 478 | (loop (- i 1)))) |
| 445 | (display (make-string indent #\space) port) | 479 | (display (make-string indent #\space) port) |
| 446 | indent) | 480 | indent) |
| 481 | ((? page-break?) | ||
| 482 | (unless delimited? (newline port)) | ||
| 483 | (display #\page port) | ||
| 484 | (newline port) | ||
| 485 | (display (make-string indent #\space) port) | ||
| 486 | indent) | ||
| 447 | (('quote lst) | 487 | (('quote lst) |
| 448 | (unless delimited? (display " " port)) | 488 | (unless delimited? (display " " port)) |
| 449 | (display "'" port) | 489 | (display "'" port) |
diff --git a/tests/read-print.scm b/tests/read-print.scm index f915b7e2d21..70be7754f8a 100644 --- a/tests/read-print.scm +++ b/tests/read-print.scm | |||
| @@ -70,6 +70,21 @@ | |||
| 70 | (read-with-comments port) | 70 | (read-with-comments port) |
| 71 | (read-with-comments port))))) | 71 | (read-with-comments port))))) |
| 72 | 72 | ||
| 73 | (test-equal "read-with-comments: top-level page break" | ||
| 74 | (list (comment ";; Begin.\n") (vertical-space 1) | ||
| 75 | (page-break) | ||
| 76 | (comment ";; End.\n")) | ||
| 77 | (call-with-input-string "\ | ||
| 78 | ;; Begin. | ||
| 79 | |||
| 80 | |||
| 81 | ;; End.\n" | ||
| 82 | (lambda (port) | ||
| 83 | (list (read-with-comments port) | ||
| 84 | (read-with-comments port) | ||
| 85 | (read-with-comments port) | ||
| 86 | (read-with-comments port))))) | ||
| 87 | |||
| 73 | (test-pretty-print "(list 1 2 3 4)") | 88 | (test-pretty-print "(list 1 2 3 4)") |
| 74 | (test-pretty-print "((a . 1) (b . 2))") | 89 | (test-pretty-print "((a . 1) (b . 2))") |
| 75 | (test-pretty-print "(a b c . boom)") | 90 | (test-pretty-print "(a b c . boom)") |
| @@ -229,6 +244,13 @@ mnopqrstuvwxyz.\")" | |||
| 229 | ;; Comment after blank line. | 244 | ;; Comment after blank line. |
| 230 | two)") | 245 | two)") |
| 231 | 246 | ||
| 247 | (test-pretty-print "\ | ||
| 248 | (begin | ||
| 249 | break | ||
| 250 | |||
| 251 | ;; page break above | ||
| 252 | end)") | ||
| 253 | |||
| 232 | (test-equal "pretty-print-with-comments, canonicalize-comment" | 254 | (test-equal "pretty-print-with-comments, canonicalize-comment" |
| 233 | "\ | 255 | "\ |
| 234 | (list abc | 256 | (list abc |
