Recently Written · git

blaher

Gilbert Baumann's blaher

git clone https://github.com/equwal/blaher

Log | Files | Refs


blah.lisp (1748 bytes)

1 (defpackage :blah
2   (:use :common-lisp)
3   (:export #:blah #:blaher))
4 
5 (in-package :blah)
6 
7 (defun blah (stream template &rest args)
8   (loop for x in (parse-blah template) do (princ (getf args x x) stream)))
9 
10 (define-compiler-macro blah (&whole whole stream template &rest args)
11   (if (stringp template)
12       `(funcall (blaher ,template) ,stream ,@args)
13       whole))
14 
15 (defmacro blaher (template)
16   (let* ((template (parse-blah template))
17          (stream (gensym "STREAM."))
18          (params (mapcar #'(lambda (x) (list x (gensym)))
19                          (remove-duplicates
20                           (remove-if-not #'symbolp template)))))
21     `(lambda (,stream &key ,@(mapcar #'list params))
22        ,@(mapcar (lambda (x)
23                    `(princ ,(or (cadr (assoc x params)) x) ,stream))
24                  template))))
25 
26 (defun parse-blah (string &optional (start 0))
27   (let* ((p1 (search "{{" string :start2 start))
28          (p2 (and p1 (search "}}" string :start2 p1))))
29     (cons (subseq string start (and p2 p1))
30           (and p2 (cons (intern (string-upcase
31                                  (subseq string (+ p1 2) p2))
32                                 :keyword)
33                         (parse-blah string (+ p2 2)))))))
34 
35 ;; (blaher "Hi {{person}}! I am {{computer-assistant}}, here to help you, {{person}}, with all of your problems.")
36 
37 ;; macro expands to:
38 
39 ;; (LAMBDA (#:STREAM.6790 &KEY ((:COMPUTER-ASSISTANT #:G6791))
40 ;;          ((:PERSON #:G6792)))
41 ;;   (PRINC "Hi " #:STREAM.6790)
42 ;;   (PRINC #:G6792 #:STREAM.6790)
43 ;;   (PRINC "! I am " #:STREAM.6790)
44 ;;   (PRINC #:G6791 #:STREAM.6790)
45 ;;   (PRINC ", here to help you, " #:STREAM.6790)
46 ;;   (PRINC #:G6792 #:STREAM.6790)
47 ;;   (PRINC ", with all of your problems." #:STREAM.6790))