read-print.scm 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2021-2023 Ludovic Courtès <ludo@gnu.org>
  3. ;;;
  4. ;;; This file is part of GNU Guix.
  5. ;;;
  6. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  7. ;;; under the terms of the GNU General Public License as published by
  8. ;;; the Free Software Foundation; either version 3 of the License, or (at
  9. ;;; your option) any later version.
  10. ;;;
  11. ;;; GNU Guix is distributed in the hope that it will be useful, but
  12. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;;; GNU General Public License for more details.
  15. ;;;
  16. ;;; You should have received a copy of the GNU General Public License
  17. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  18. (define-module (tests-style)
  19. #:use-module (guix read-print)
  20. #:use-module (guix gexp) ;for the reader extensions
  21. #:use-module (srfi srfi-34)
  22. #:use-module (srfi srfi-35)
  23. #:use-module (srfi srfi-64)
  24. #:use-module (ice-9 match))
  25. (define-syntax-rule (test-pretty-print str args ...)
  26. "Test equality after a round-trip where STR is passed to
  27. 'read-with-comments' and the resulting sexp is then passed to
  28. 'pretty-print-with-comments'."
  29. (test-equal str
  30. (call-with-output-string
  31. (lambda (port)
  32. (let ((exp (call-with-input-string str
  33. read-with-comments)))
  34. (pretty-print-with-comments port exp args ...))))))
  35. (define-syntax-rule (test-pretty-print/sequence str args ...)
  36. "Likewise, but read and print entire sequences rather than individual
  37. expressions."
  38. (test-equal str
  39. (call-with-output-string
  40. (lambda (port)
  41. (let ((lst (call-with-input-string str
  42. read-with-comments/sequence)))
  43. (pretty-print-with-comments/splice port lst args ...))))))
  44. (test-begin "read-print")
  45. (test-assert "read-with-comments: missing closing paren"
  46. (guard (c ((error? c) #t))
  47. (call-with-input-string "(what is going on?"
  48. read-with-comments)))
  49. (test-equal "read-with-comments: dot notation"
  50. (cons 'a 'b)
  51. (call-with-input-string "(a . b)"
  52. read-with-comments))
  53. (test-equal "read-with-comments: half dot notation"
  54. '(lambda x x)
  55. (call-with-input-string "(lambda (. x) x)"
  56. read-with-comments))
  57. (test-equal "read-with-comments: list with blank line"
  58. `(list with ,(vertical-space 1) blank line)
  59. (call-with-input-string "\
  60. (list with
  61. blank line)\n"
  62. read-with-comments))
  63. (test-equal "read-with-comments: list with multiple blank lines"
  64. `(list with ,(comment ";multiple\n" #t)
  65. ,(vertical-space 3) blank lines)
  66. (call-with-input-string "\
  67. (list with ;multiple
  68. blank lines)\n"
  69. read-with-comments))
  70. (test-equal "read-with-comments: top-level blank lines"
  71. (list (vertical-space 2) '(a b c) (vertical-space 2))
  72. (call-with-input-string "
  73. (a b c)\n\n"
  74. (lambda (port)
  75. (list (read-with-comments port)
  76. (read-with-comments port)
  77. (read-with-comments port)))))
  78. (test-equal "read-with-comments: top-level page break"
  79. (list (comment ";; Begin.\n") (vertical-space 1)
  80. (page-break)
  81. (comment ";; End.\n"))
  82. (call-with-input-string "\
  83. ;; Begin.
  84. ;; End.\n"
  85. (lambda (port)
  86. (list (read-with-comments port)
  87. (read-with-comments port)
  88. (read-with-comments port)
  89. (read-with-comments port)))))
  90. (test-pretty-print "(list 1 2 3 4)")
  91. (test-pretty-print "((a . 1) (b . 2))")
  92. (test-pretty-print "(a b c . boom)")
  93. (test-pretty-print "(list 1
  94. 2
  95. 3
  96. 4)"
  97. #:long-list 3
  98. #:indent 20)
  99. (test-pretty-print "\
  100. (list abc
  101. def)"
  102. #:max-width 11)
  103. (test-pretty-print "\
  104. (#:foo
  105. #:bar)"
  106. #:max-width 10)
  107. (test-pretty-print "\
  108. (#:first 1
  109. #:second 2
  110. #:third 3)")
  111. (test-pretty-print "\
  112. ((x
  113. 1)
  114. (y
  115. 2)
  116. (z
  117. 3))"
  118. #:max-width 3)
  119. (test-pretty-print "\
  120. (let ((x 1)
  121. (y 2)
  122. (z 3)
  123. (p 4))
  124. (+ x y))"
  125. #:max-width 11)
  126. (test-pretty-print "\
  127. (begin
  128. 1+ 1- 123/ 456*
  129. (1+ 41))")
  130. (test-pretty-print "\
  131. (lambda (x y)
  132. ;; This is a procedure.
  133. (let ((z (+ x y)))
  134. (* z z)))")
  135. (test-pretty-print "\
  136. (case x
  137. ((1)
  138. 'one)
  139. ((2)
  140. 'two))")
  141. (test-pretty-print "\
  142. (cond
  143. ((zero? x)
  144. 'zero)
  145. ((odd? x)
  146. 'odd)
  147. (else #f))")
  148. (test-pretty-print "\
  149. #~(string-append #$coreutils \"/bin/uname\")")
  150. (test-pretty-print "\
  151. (package
  152. (inherit coreutils)
  153. (version \"42\"))")
  154. (test-pretty-print "\
  155. (modify-phases %standard-phases
  156. (add-after 'unpack 'post-unpack
  157. (lambda _
  158. #t))
  159. (add-before 'check 'pre-check
  160. (lambda* (#:key inputs #:allow-other-keys)
  161. do things ...)))")
  162. (test-pretty-print "\
  163. (#:phases (modify-phases sdfsdf
  164. (add-before 'x 'y
  165. (lambda _
  166. xyz))))")
  167. (test-pretty-print "\
  168. (string-append \"a\\tb\" \"\\n\")")
  169. (test-pretty-print "\
  170. (display \"This is a very long string.
  171. It contains line breaks, which are preserved,
  172. because it's a long string.\")")
  173. (test-pretty-print "\
  174. (description \"abcdefghijkl
  175. mnopqrstuvwxyz.\")"
  176. #:max-width 30)
  177. (test-pretty-print "\
  178. (description
  179. \"abcdefghijkl
  180. mnopqrstuvwxyz.\")"
  181. #:max-width 12)
  182. (test-pretty-print "\
  183. (description
  184. \"abcdefghijklmnopqrstuvwxyz\")"
  185. #:max-width 33)
  186. (test-pretty-print "\
  187. (list ;margin comment
  188. a b c)")
  189. (test-pretty-print "\
  190. (list
  191. ;; This is a line comment immediately following the list head.
  192. #:test-flags #~(list \"-m\" \"not external and not samples\"))")
  193. (test-pretty-print "\
  194. (modify-phases %standard-phases
  195. (replace 'build
  196. ;; Nicely indented in 'modify-phases' context.
  197. (lambda _
  198. #t)))")
  199. (test-pretty-print "\
  200. (modify-inputs inputs
  201. ;; Regular indentation for 'replace' here.
  202. (replace \"gmp\" gmp))")
  203. (test-pretty-print "\
  204. #~(modify-phases phases
  205. (add-after 'whatever 'something-else
  206. (lambda _
  207. ;; This comment appears inside a gexp.
  208. 42)))")
  209. (test-pretty-print "\
  210. #~(list #$@(list coreutils ;yup
  211. grep) ;margin comment
  212. #+sed
  213. ;; Line comment.
  214. #$grep)")
  215. (test-pretty-print "\
  216. (package
  217. ;; Here 'sha256', 'base32', and 'arguments' must be
  218. ;; immediately followed by a newline.
  219. (source (origin
  220. (method url-fetch)
  221. (sha256
  222. (base32
  223. \"not a real base32 string\"))))
  224. (arguments
  225. '(#:phases %standard-phases
  226. #:tests? #f)))")
  227. ;; '#:key value' is kept on the same line.
  228. (test-pretty-print "\
  229. (package
  230. (name \"keyword-value-same-line\")
  231. (arguments
  232. (list #:phases #~(modify-phases %standard-phases
  233. (add-before 'x 'y
  234. (lambda* (#:key inputs #:allow-other-keys)
  235. (foo bar baz))))
  236. #:make-flags #~'(\"ANSWER=42\")
  237. #:tests? #f)))")
  238. (test-pretty-print "\
  239. (let ((x 1)
  240. (y 2)
  241. (z (let* ((a 3)
  242. (b 4))
  243. (+ a b))))
  244. (list x y z))")
  245. (test-pretty-print "\
  246. (begin
  247. (chmod \"foo\" #o750)
  248. (chmod port
  249. (logand #o644
  250. (lognot (umask))))
  251. (logand #x7f xyz))")
  252. (test-pretty-print "\
  253. (substitute-keyword-arguments (package-arguments x)
  254. ((#:phases phases)
  255. `(modify-phases ,phases
  256. (add-before 'build 'do-things
  257. (lambda _
  258. #t))))
  259. ((#:configure-flags flags)
  260. `(cons \"--without-any-problem\"
  261. ,flags)))")
  262. (test-pretty-print "\
  263. (vertical-space one:
  264. two:
  265. three:
  266. end)")
  267. (test-pretty-print "\
  268. (vertical-space one
  269. ;; Comment after blank line.
  270. two)")
  271. (test-pretty-print "\
  272. (begin
  273. break
  274. ;; page break above
  275. end)")
  276. (test-pretty-print "\
  277. (home-environment
  278. (services
  279. (list (service-type home-bash-service-type))))")
  280. (test-pretty-print/sequence "\
  281. ;;; This is a top-level comment.
  282. ;; Above is a page break.
  283. (this is an sexp
  284. ;; with a comment
  285. !!)
  286. ;; The end.\n")
  287. (test-pretty-print/sequence "
  288. ;;; Hello!
  289. ;;; Notice that there are three semicolons here.
  290. (define-module (foo bar)
  291. #:use-module (guix)
  292. #:use-module (gnu))
  293. ;; And now, the OS.
  294. (operating-system
  295. (host-name \"komputilo\")
  296. (locale \"eo_EO.UTF-8\")
  297. (services
  298. (cons (service mcron-service-type) %base-services)))\n"
  299. #:format-comment canonicalize-comment)
  300. (test-equal "pretty-print-with-comments, canonicalize-comment"
  301. "\
  302. (list abc
  303. ;; Not a margin comment.
  304. ;; Ditto.
  305. ;;
  306. ;; There's a blank line above.
  307. def ;margin comment
  308. ghi)"
  309. (let ((sexp (call-with-input-string
  310. "\
  311. (list abc
  312. ;Not a margin comment.
  313. ;;; Ditto.
  314. ;;;;;
  315. ; There's a blank line above.
  316. def ;; margin comment
  317. ghi)"
  318. read-with-comments)))
  319. (call-with-output-string
  320. (lambda (port)
  321. (pretty-print-with-comments port sexp
  322. #:format-comment
  323. canonicalize-comment)))))
  324. (test-equal "pretty-print-with-comments, canonicalize-vertical-space"
  325. "\
  326. (list abc
  327. def
  328. ;; last one
  329. ghi)"
  330. (let ((sexp (call-with-input-string
  331. "\
  332. (list abc
  333. def
  334. ;; last one
  335. ghi)"
  336. read-with-comments)))
  337. (call-with-output-string
  338. (lambda (port)
  339. (pretty-print-with-comments port sexp
  340. #:format-vertical-space
  341. canonicalize-vertical-space)))))
  342. (test-equal "pretty-print-with-comments, multi-line comment"
  343. "\
  344. (list abc
  345. ;; This comment spans
  346. ;; two lines.
  347. def)"
  348. (call-with-output-string
  349. (lambda (port)
  350. (pretty-print-with-comments port
  351. `(list abc ,(comment "\
  352. ;; This comment spans\n
  353. ;; two lines.\n")
  354. def)))))
  355. (test-end)