improve #:omit

main
Matthew Butterick 10 years ago
parent 11f732d1e3
commit e950f59f06

@ -151,12 +151,12 @@
(if (char? joiner) (format "~a" joiner) joiner))
;; helper macro that applies proc to all strings found in xexpr input
(define (apply-xexpr-strings proc x [tags-to-omit '()])
(define (apply-xexpr-strings proc x [omit-test (λ(x) #f)])
; ((procedure? txexpr?) ((or/c null (listof txexpr-tag?))) . ->* . txexpr?)
(let loop ([x x])
(cond
[(string? x) (proc x)]
[(and (txexpr? x) (not (member (car x) tags-to-omit))) (cons (car x) (map loop (cdr x)))]
[(and (string? x) (not (omit-test x))) (proc x)]
[(and (txexpr? x) (not (omit-test x))) (cons (car x) (map loop (cdr x)))]
[else x])))
@ -164,11 +164,11 @@
(define+provide+safe (hyphenatef x proc [joiner default-joiner]
#:exceptions [extra-exceptions '()]
#:min-length [min-length default-min-length]
#:omit-tags [tags-to-omit '()])
#:omit [omit-test (λ(x) #f)])
((xexpr? procedure?) ((or/c char? string?)
#:exceptions (listof exception-word?)
#:min-length (or/c integer? #f)
#:omit-tags (or/c null (listof txexpr-tag?))) . ->* . xexpr/c)
#:omit ((or/c string? txexpr?) . -> . any/c)) . ->* . xexpr/c)
;; set up module data
;; todo?: change set! to parameterize
@ -181,28 +181,28 @@
(define (insert-hyphens text)
(regexp-replace* word-pattern text (λ(word) (if (proc word) (string-join (word->hyphenation-points word min-length) joiner-string) word))))
(apply-xexpr-strings insert-hyphens x tags-to-omit))
(apply-xexpr-strings insert-hyphens x omit-test))
;; Default hyphenate is a special case of hyphenatef.
(define+provide+safe (hyphenate x [joiner default-joiner]
#:exceptions [extra-exceptions '()]
#:min-length [min-length default-min-length]
#:omit-tags [tags-to-omit '()])
#:omit [omit-test (λ(x) #f)])
((xexpr/c) ((or/c char? string?)
#:exceptions (listof exception-word?)
#:min-length (or/c integer? #f)
#:omit-tags (or/c null (listof txexpr-tag?))) . ->* . xexpr/c)
(hyphenatef x (λ(x) #t) joiner #:exceptions extra-exceptions #:min-length min-length #:omit-tags tags-to-omit))
#:omit ((or/c string? txexpr?) . -> . any/c)) . ->* . xexpr/c)
(hyphenatef x (λ(x) #t) joiner #:exceptions extra-exceptions #:min-length min-length #:omit omit-test))
;; Remove hyphens.
(define+provide+safe (unhyphenate x [joiner default-joiner])
((xexpr/c) ((or/c char? string?)) . ->* . xexpr/c)
(define+provide+safe (unhyphenate x [joiner default-joiner] #:omit [omit-test (λ(x) #f)])
((xexpr/c) ((or/c char? string?) #:omit ((or/c string? txexpr?) . -> . any/c)) . ->* . xexpr/c)
(define (remove-hyphens text)
(string-replace text (joiner->string joiner) ""))
(apply-xexpr-strings remove-hyphens x))
(apply-xexpr-strings remove-hyphens x omit-test))

@ -40,7 +40,7 @@ Safe mode enables the function contracts documented below. Use safe mode by impo
[joiner (or/c char? string?) (integer->char #x00AD)]
[#:exceptions exceptions (listof string?) empty]
[#:min-length length (or/c integer? false?) 5]
[#:omit-tags tags (or/c null (listof txexpr-tag?)) null])
[#:omit test ((or/c string? txexpr?) . -> . any/c) (λ(x) #f)])
xexpr/c]
Hyphenate @racket[_xexpr] by calculating hyphenation points and inserting @racket[_joiner] at those points. By default, @racket[_joiner] is the soft hyphen (Unicode 00AD = decimal 173). Words shorter than @racket[#:min-length] @racket[_length] will not be hyphenated. To hyphenate words of any length, use @racket[#:min-length] @racket[#f].
@ -103,12 +103,14 @@ Don't send raw HTML or XML through @racket[hyphenate]. It can't distinguish tags
(xexpr->string (hyphenate (string->xexpr html) #\-))
]
If you're working with HTML, be careful not to include any @code{<script>} or @code{<style>} blocks, which contain non-hyphenatable data. You can protect that data by using the @racket[#:omit-tags] keyword argument, which will skip over the listed tags.
If you're working with HTML, be careful not to include any @code{<script>} or @code{<style>} blocks, which contain non-hyphenatable data. You can protect that data by using the @racket[#:omit] keyword to provide a @racket[_test]. The @racket[_test] will be applied to all tagged X-expressions (see @racket[txexpr?]) and strings. When @racket[_test] evaluates to true, the item will be skipped.
@examples[#:eval my-eval
(hyphenate '(body "hyphenate" (script "don't hyphenate")) #\-)
(hyphenate '(body "hyphenate" (script "don't hyphenate")) #\-
#:omit-tags '(script))
(hyphenate '(body "processing" (script "no processing")) #\-)
(hyphenate '(body "processing" (script "no processing")) #\-
#:omit (λ(x) (and (txexpr? x) (member (get-tag x) '(script)))))
(hyphenate '(body "processing" (script "no processing")) #\-
#:omit (λ(x) (and (string? x) (regexp-match #rx"^no" x))))
]
@ -119,7 +121,7 @@ If you're working with HTML, be careful not to include any @code{<script>} or @c
[joiner (or/c char? string?) (integer->char \#x00AD)]
[#:exceptions exceptions (listof string?) empty]
[#:min-length length (or/c integer? false?) 5]
[#:omit-tags tags (or/c null (listof txexpr-tag?)) null])
[#:omit test ((or/c string? txexpr?) . -> . any/c) (λ(x) #f)])
xexpr/c]
Like @racket[hyphenate], but only words matching @racket[_pred] are hyphenated. Convenient if you want to prevent hyphenation of certain sets of words, like proper names:
@ -147,7 +149,8 @@ It's possible to do fancier kinds of hyphenation restrictions that take account
@defproc[
(unhyphenate
[xexpr xexpr/c]
[joiner (or/c char? string?) @(integer->char #x00AD)])
[joiner (or/c char? string?) @(integer->char #x00AD)]
[#:omit test ((or/c string? txexpr?) . -> . any/c) (λ(x) #f)])
xexpr/c]
Remove @racket[_joiner] from @racket[_xexpr]. Like @racket[hyphenate], it works on nested X-expressions.

@ -26,11 +26,28 @@
(check-false (exception-word? "foo bar"))
(check-equal? (hyphenate '(p "circular polymorphism" amp (em "squandering")) #:omit-tags '(em))
;; omit certain tags
(check-equal? (hyphenate '(p "circular polymorphism" amp (em "squandering")) #:omit (λ(x) (and (txexpr? x) (member (car x) '(em)))))
'(p "cir\u00ADcu\u00ADlar poly\u00ADmor\u00ADphism" amp (em "squandering")))
(check-equal? (hyphenate '(p "circular polymorphism" amp (em "squandering")) #:omit-tags '(p))
(check-equal? (hyphenate '(p "circular polymorphism" amp (em "squandering")) #:omit (λ(x) (and (txexpr? x) (member (car x) '(p)))))
'(p "circular polymorphism" amp (em "squandering")))
(check-equal? (hyphenate '(p (foo "circular") (bar "circular") (zam "circular")) #:omit-tags '(foo zam))
'(p (foo "circular") (bar "cir\u00ADcu\u00ADlar") (zam "circular")))
(check-equal? (hyphenate '(p (foo "circular") (bar "circular") (zam "circular")) #:omit (λ(x) (and (txexpr? x) (member (car x) '(foo zam)))))
'(p (foo "circular") (bar "cir\u00ADcu\u00ADlar") (zam "circular")))
(require txexpr)
; omit txexprs with an attribute
(check-equal? (hyphenate '(p (foo ((hyphens "no-thanks")) "circular") (foo "circular"))
#:omit (λ(x) (and (txexpr? x)
(with-handlers ([exn:fail? (λ(exn) #f)])
(equal? (attr-ref x 'hyphens) "no-thanks")))))
'(p (foo ((hyphens "no-thanks")) "circular") (foo "cir\u00ADcu\u00ADlar")))
;; omit strings that end with "s"
(check-equal? (hyphenate '(p (foo "tailfeathers") (foo "tailfeather")) #:omit (λ(x) (and (string? x) (regexp-match #rx"s$" x))))
'(p (foo "tailfeathers") (foo "tail\u00ADfeath\u00ADer")))
(check-equal? (unhyphenate '(p (script "tail-feathers") (em "tail-feathers")) #\- #:omit (λ(x) (and (txexpr? x) (member (car x) '(script)))))
'(p (script "tail-feathers") (em "tailfeathers")))
Loading…
Cancel
Save