Created
September 19, 2019 02:47
-
-
Save belmarca/e79685b751950920f5da00461d3d8818 to your computer and use it in GitHub Desktop.
gerbil quasistring
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; quasistring.ss | |
(import :std/format | |
:std/net/request) | |
;; variant: return procedure of n args? | |
(defsyntax (quasistring stx) | |
(syntax-case stx () | |
((macro s) | |
(stx-string? #'s) | |
(let (port (open-input-string (stx-e #'s))) | |
(let lp ((c (read-char port)) | |
(sexps []) | |
(str [])) | |
(cond | |
((eq? c #\#) ;; template variable? | |
(let ((c+1 (read-char port))) | |
(cond | |
((eq? c+1 #\{) ;; yes, read sexp | |
(let (ssexp (read port)) | |
(if (eq? (read-char port) #\}) ;; closed template variable? | |
(lp (read-char port) (cons ssexp sexps) (cons #\a (cons #\~ str))) | |
(error "Bad quasistring formatting.")))) | |
(else ;; no, start again | |
(lp (read-char port) sexps str))))) | |
((eq? c #!eof) ;; eof so return syntax | |
(close-input-port port) | |
(with-syntax (((vars ...) (datum->syntax #'macro (reverse sexps))) | |
(str (list->string (reverse str)))) | |
#'(apply format str [vars ...]))) | |
(else ;; no, start again | |
(lp (read-char port) sexps (cons c str))))))))) | |
;; > (let ((a 1) (b 2)) (quasistring "a: #{a}~nb: #{b}")) | |
;; "a: 1\nb: 2" | |
;; > (let ((a 1) (b 2)) (quasistring "a: #{b}~nb: #{b}")) | |
;; "a: 2\nb: 2" | |
;; > (let (name "world") (quasistring "hello, #{name}!")) | |
;; "hello, world!" | |
;; > (quasistring "hello, #{name}!") | |
;; *** ERROR -- Unbound variable: name | |
;; > (quasistring "2 + 2 is #{(+ 2 2)}") | |
;; "2 + 2 is 4" | |
;; > (quasistring "Your IP address is #{(let (req (http-get \"ipinfo.io/json\")) (hash-ref (request-json req) 'ip))}") | |
;; "Your IP address is x.x.x.x" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment