add splitf-txexpr

dev-validator
Matthew Butterick 10 years ago
parent ac05431c5e
commit 73c8d8db8b

@ -192,4 +192,19 @@
(procedure? txexpr? . -> . txexpr?)
(map-elements/exclude proc x (λ(x) #f)))
;; function to split tag out of txexpr
(define+provide/contract (splitf-txexpr tx proc)
(txexpr? procedure? . -> . (values (listof txexpr-element?) txexpr?))
(define matches empty)
(define (do-extraction x)
(cond
[(proc x) (begin ; store matched item but return empty value
(set! matches (cons x matches))
empty)]
[(txexpr? x) (let-values([(tag attr body) (txexpr->values x)])
(make-txexpr tag attr (do-extraction body)))]
[(txexpr-elements? x) (filter-not empty? (map do-extraction x))]
[else x]))
(define tx-extracted (do-extraction tx)) ;; do this first to fill matches
(values (reverse matches) tx-extracted))

@ -376,6 +376,20 @@ Be careful with the wider consequences of exclusion tests. When @racket[_exclude
(map-elements/exclude upcaser tx (λ(x) (equal? (get-tag x) 'div)))
]
@defproc[
(splitf-txexpr
[tx txexpr?]
[pred procedure?])
(values (listof txexpr-element?) txexpr?)]
Recursively descend through @racket[_txexpr] and extract all elements that match @racket[_pred]. Returns two values: a list of matching elements, and the @racket[_txexpr] with the elements removed. Sort of esoteric, but I've needed it more than once, so here it is.
@examples[#:eval my-eval
(define tx '(div "Wonderful day" (meta "weather" "good") "for a walk"))
(define remove? (λ(x) (and (txexpr? x) (equal? 'meta (get-tag x)))))
(splitf-txexpr tx remove?)
]
@section{License & source code}
This module is licensed under the LGPL.

@ -105,9 +105,14 @@
(check-equal? (map-elements (λ(x) (if (string? x) "boing" x))
'(p "foo" "bar" (em "square")))
'(p "foo" "bar" (em "square")))
'(p "boing" "boing" (em "boing")))
(define split-this-tx '(root (meta "foo" "bar") "hello" "world" (meta "foo2" "bar2")
(em "goodnight" "moon" (meta "foo3" "bar3"))))
(check-equal? (call-with-values (λ() (splitf-txexpr split-this-tx (λ(x) (and (txexpr? x) (equal? 'meta (car x)))))) list)
(list '((meta "foo" "bar") (meta "foo2" "bar2") (meta "foo3" "bar3"))
'(root "hello" "world" (em "goodnight" "moon"))))

Loading…
Cancel
Save