You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
typesetting/quad/quad/atomize.rkt

53 lines
2.6 KiB
Racket

6 years ago
#lang sugar/debug racket/base
(require racket/contract racket/match racket/list txexpr racket/dict
"quad.rkt" "qexpr.rkt" "param.rkt")
8 years ago
(provide (all-defined-out))
6 years ago
(define (update-with base-hash . update-hashes)
;; starting with base-hash, add or update keys found in update-hashes
(apply hasheq (flatten (map hash->list (list* base-hash update-hashes)))))
(module+ test
(check-equal?
((hasheq 'foo "bar" 'zim "zam") . update-with . (hasheq 'zim "BANG") (hasheq 'toe "jam") (hasheq 'foo "zay"))
'#hasheq((zim . "BANG") (foo . "zay") (toe . "jam"))))
6 years ago
(define/contract (atomize qx)
6 years ago
;; normalize a quad by reducing it to one-character quads.
;; propagate attrs downward.
6 years ago
(quad? . -> . (listof atomic-quad?))
6 years ago
(let loop ([x qx][attrs (current-default-attrs)])
6 years ago
(match x
6 years ago
[(? char? c) (list (q attrs c))]
[(? string?) (append* (for/list ([c (in-string x)]) ;; strings are exploded
(loop c attrs)))]
[($quad this-attrs elems) ;; qexprs with attributes are recursed
(define merged-attrs (attrs . update-with . this-attrs))
(append* (for/list ([elem (in-list elems)])
(loop elem merged-attrs)))]
6 years ago
[else (raise-argument-error 'atomize "valid item" x)])))
8 years ago
(module+ test
(require rackunit)
6 years ago
(check-equal? (atomize (q "Hi")) (list (q #\H) (q #\i)))
(check-equal? (atomize (q "Hi " (q "You"))) (list (q #\H) (q #\i) (q #\space) (q #\Y) (q #\o) (q #\u)))
(check-exn exn:fail:contract? (λ () (atomize #t)))
6 years ago
;; with attributes
6 years ago
(check-equal? (atomize (q (hasheq 'k "v") "Hi")) (list (q (hasheq 'k "v") #\H) (q (hasheq 'k "v") #\i)))
(check-equal? (atomize (q (hasheq 'k "v") "Hi " (q "You")))
(list
($quad '#hasheq((k . "v")) '(#\H))
($quad '#hasheq((k . "v")) '(#\i))
($quad '#hasheq((k . "v")) '(#\space))
($quad '#hasheq((k . "v")) '(#\Y))
($quad '#hasheq((k . "v")) '(#\o))
($quad '#hasheq((k . "v")) '(#\u))))
(check-equal? (atomize (q (hasheq 'k1 "v1" 'k2 42) "Hi " (q (hasheq 'k1 "v2" 'k3 "foo") "You")))
(list
($quad '#hasheq((k1 . "v1") (k2 . 42)) '(#\H))
($quad '#hasheq((k1 . "v1") (k2 . 42)) '(#\i))
($quad '#hasheq((k1 . "v1") (k2 . 42)) '(#\space))
($quad '#hasheq((k1 . "v2") (k2 . 42) (k3 . "foo")) '(#\Y))
($quad '#hasheq((k1 . "v2") (k2 . 42) (k3 . "foo")) '(#\o))
($quad '#hasheq((k1 . "v2") (k2 . 42) (k3 . "foo")) '(#\u)))))