ref: 22dc4268f62e3cc16b17525ec4c1f9e0e6ccdcb4
parent: 476b3ea3a5d3791c51daa633b800ec0c76435a33
author: Matthew Flatt <mflatt@racket-lang.org>
date: Fri Apr 22 02:05:18 CDT 2022
Zuo: parse `#` in as a comment in `config-file->hash`
--- a/lib/zuo/config.zuo
+++ b/lib/zuo/config.zuo
@@ -36,7 +36,7 @@
[positions
(define var (string->symbol (substring line (car positions) (cadr positions))))
(define rhs (substring line (+ (list-ref positions 2) 1) (string-length line)))
- (hash-set accum var (string-trim rhs))]
+ (hash-set accum var (string-trim (remove-makefile-comment rhs)))]
[else accum]))
(hash)
lines))
@@ -44,3 +44,23 @@
(hash-set config key (hash-ref vars key) ))
config
(hash-keys vars)))
+
+(define (remove-makefile-comment s)
+ (define l (string-split s "#"))
+ (cond
+ [(= (length l) 1) s]
+ [else
+ ;; A `\` just before `#` escapes the `#`
+ (let loop ([l l])
+ (cond
+ [(null? l) ""]
+ [else
+ (let* ([s (car l)]
+ [len (string-length s)])
+ (cond
+ [(= len 0) ""]
+ [(= (char "\\") (string-ref s (- len 1)))
+ (~a (substring s 0 (- len 1))
+ "#"
+ (loop (cdr l)))]
+ [else s]))]))]))
--- /dev/null
+++ b/tests/config.zuo
@@ -1,0 +1,45 @@
+#lang zuo
+
+(require "harness.zuo")
+
+(alert "config")
+
+(define Mf-config (build-path tmp-dir "Mf-config"))
+
+(define (config->hash content [overrides (hash)])
+ (display-to-file content Mf-config :truncate)
+ (config-file->hash Mf-config overrides))
+
+(check (config->hash "") (hash))
+(check (config->hash "" (hash 'X "x")) (hash 'X "x"))
+(check (config->hash "This is not a confg line" (hash 'X "x")) (hash 'X "x"))
+(check (config->hash "Comment # no=6" (hash 'X "x")) (hash 'X "x"))
+
+(check (config->hash "X=5") (hash 'X "5"))
+(check (config->hash "X =5") (hash 'X "5"))
+(check (config->hash "X= 5 ") (hash 'X "5"))
+(check (config->hash " X = 5 ") (hash 'X "5"))
+(check (config->hash "\n\n X = 5 \n\n") (hash 'X "5"))
+(check (config->hash "X = 5\\\n1") (hash 'X "51"))
+
+(check (config->hash "X_1=5") (hash 'X_1 "5"))
+(check (config->hash "abcdefg_ZXSGFH_=5") (hash 'abcdefg_ZXSGFH_ "5"))
+(check (config->hash "123=5") (hash (string->symbol "123") "5"))
+(check (config->hash "1%23=5") (hash))
+(check (config->hash "x%23=5") (hash))
+
+(check (config->hash "X=5\nY=8") (hash 'X "5" 'Y "8"))
+(check (config->hash "X=5\nX=8") (hash 'X "8"))
+(check (config->hash "X=5\nX=8" (hash 'X "0")) (hash 'X "0"))
+(check (config->hash "X=5\nY=8" (hash 'X "0")) (hash 'X "0" 'Y "8"))
+
+(check (config->hash "X=5 # Comment after") (hash 'X "5"))
+(check (config->hash "X=5 # Comment after\nY=8") (hash 'X "5" 'Y "8"))
+(check (config->hash "X=5 \\# 7") (hash 'X "5 # 7"))
+(check (config->hash "X=5 \\\\# 7") (hash 'X "5 \\# 7"))
+(check (config->hash "X=5# \\\\# 7") (hash 'X "5"))
+(check (config->hash "X=# # #") (hash 'X ""))
+(check (config->hash "X = 5\\\n# 1 \\\n 2") (hash 'X "5"))
+(check (config->hash "X = 5\\\n 1 \\\n 2") (hash 'X "5 1 2"))
+
+(rm* Mf-config)
--- a/tests/main.zuo
+++ b/tests/main.zuo
@@ -21,6 +21,7 @@
(require "cleanable.zuo")
(require "image.zuo")
(require "shell.zuo")
+(require "config.zuo")
(require "c.zuo")
(require "cycle.zuo")
(require "form.zuo")
--- a/zuo-doc/zuo-lib.scrbl
+++ b/zuo-doc/zuo-lib.scrbl
@@ -304,15 +304,18 @@
@nonterm{name} @litchar{=} @nonterm{value}, with any number of ignored
spaces at the start of the line, end of the line, or around the
@litchar{=}, and with a trailing @litchar{\} on a line deleted along
-with its newline (to create a single line). Each @nonterm{name}
-consists of alphanumeric characters and @litchar{_}; the symbol form
-of the name is used as a key in the resulting hash table, mapped to
-the @nonterm{value} as a string. Lines in @racket[file] that do not
-match the configuration format are ignored. If a same @nonterm{name}
-is configured multiple times, the last mapping overrides earlier
-ones.
+with its newline (to create a single line). A @litchar{#} character
+terminates a line to start a comment, unless the @litchar{#} is
+preceded by @litchar{\}, in which case the @litchar{\#} combination is
+parsed as a literal @litchar{#}.
+Each @nonterm{name} consists of alphanumeric characters and
+@litchar{_}; the symbol form of the name is used as a key in the
+resulting hash table, mapped to the @nonterm{value} as a string. Lines
+in @racket[file] that do not match the configuration format are
+ignored. If a same @nonterm{name} is configured multiple times, the
+last mapping overrides earlier ones.
+
After reading @racket[file], keys from @racket[overrides] are merged
to the result hash table, where values in @racket[overrides] replace
ones read from @racket[file].}
-