#lang racket/base
(require racket/splicing
(prefix-in scribble: scribble/decode)
(prefix-in scribble: scribble/core)
(for-syntax racket/base
racket/block))
(provide declare-tags tag)
(begin-for-syntax
(define SCRIBBLE-TAGS-ENV-VAR "SCRIBBLE_TAGS")
(define known-tags (make-hash))
(define (check-known-tag! src-stx tag-stx)
(cond
[(hash-has-key? known-tags (syntax-e tag-stx))
(void)]
[else
(raise-syntax-error #f "Tag has not been declared with declare-tags." src-stx tag-stx)]))
(define (generate-tagged-for-code src-stx tags bodies)
(with-syntax ([(body ...) bodies])
(for ([t tags]) (check-known-tag! src-stx t))
(define enabled-tags
(if (getenv SCRIBBLE-TAGS-ENV-VAR)
(map string->symbol (regexp-split #px"\\s+" (getenv SCRIBBLE-TAGS-ENV-VAR)))
'()))
(cond
[(for/or ([tag tags]) (member (syntax-e tag) enabled-tags))
#'(scribble:splice (list body ...))]
[else
#'(scribble:splice (list))]))))
(define-syntax (declare-tags stx)
(syntax-case stx ()
[(_ tag-name ...)
#'(begin
(begin-for-syntax
(for ([tag '(tag-name ...)])
(hash-set! known-tags tag #t)))
(define-syntax (tag-name stx-2)
(syntax-case stx-2 ()
[(_ body (... ...))
(syntax/loc stx-2
(tag tag-name body (... ...)))]
[else
(raise-syntax-error #f "~s is a tag, not a normal expression" stx-2)]))
...)]))
(define-syntax (tag stx)
(syntax-case stx ()
[(_ tag body ...)
(identifier? #'tag)
(generate-tagged-for-code stx (list #'tag) #'(body ...))]
[(_ (tag ...) body ...)
(andmap identifier? (syntax->list #'(tag ...)))
(generate-tagged-for-code stx (syntax->list #'(tag ...)) #'(body ...))]))