|
|
|
@ -8,34 +8,6 @@
|
|
|
|
|
[(_ EXPR ...) (with-syntax ([debug (datum->syntax stx 'debug)])
|
|
|
|
|
#'(when debug (report EXPR ...)))]))
|
|
|
|
|
|
|
|
|
|
(define (wrap xs
|
|
|
|
|
[target-size (current-wrap-distance)]
|
|
|
|
|
[debug #f]
|
|
|
|
|
#:hard-break [hard-break? (λ (x) #f)]
|
|
|
|
|
#:soft-break [soft-break? (λ (x) #f)]
|
|
|
|
|
#:wrap-anywhere? [wrap-anywhere? #f]
|
|
|
|
|
#:finish-wrap [finish-wrap-proc (λ (xs q idx) (list xs))])
|
|
|
|
|
#;((listof quad?)
|
|
|
|
|
(real?
|
|
|
|
|
any/c
|
|
|
|
|
#:hard-break (quad? . -> . any/c)
|
|
|
|
|
#:soft-break (quad? . -> . any/c)
|
|
|
|
|
#:finish-wrap ((listof any/c) quad? natural? . -> . (listof any/c))) . ->* . (listof any/c))
|
|
|
|
|
|
|
|
|
|
;; the hard breaks are used to divide the wrap territory into smaller chunks
|
|
|
|
|
;; that can be cached, parallelized, etc.
|
|
|
|
|
(let loop ([wraps null][qs xs])
|
|
|
|
|
(match qs
|
|
|
|
|
;; ignore a trailing hard break
|
|
|
|
|
[(or (? null?) (list (? hard-break?))) (append* (reverse wraps))]
|
|
|
|
|
[(or (cons (? hard-break?) rest) rest)
|
|
|
|
|
(define-values (head tail) (splitf-at rest (λ (x) (not (hard-break? x)))))
|
|
|
|
|
;; head will be empty (intentionally) if qs starts with two hard breaks
|
|
|
|
|
;; because there should be a blank wrap in between
|
|
|
|
|
(define next-wrap (wrap-soft-breaks head target-size debug soft-break? wrap-anywhere? finish-wrap-proc))
|
|
|
|
|
(debug-report next-wrap)
|
|
|
|
|
(loop (cons next-wrap wraps) tail)])))
|
|
|
|
|
|
|
|
|
|
(define (nonprinting-at-start? x) (not (printable? x 'start)))
|
|
|
|
|
(define (nonprinting-at-end? x) (not (printable? x 'end)))
|
|
|
|
|
(define (nonprinting-soft-break-in-middle? x) (and (not (printable? x)) (soft-break? x)))
|
|
|
|
@ -45,12 +17,14 @@
|
|
|
|
|
;; thus beginning of list represents the end of the wrap
|
|
|
|
|
(append partial (dropf wrap nonprinting-soft-break-in-middle?)))
|
|
|
|
|
|
|
|
|
|
(define (wrap-soft-breaks qs
|
|
|
|
|
target-size
|
|
|
|
|
debug
|
|
|
|
|
soft-break?
|
|
|
|
|
wrap-anywhere?
|
|
|
|
|
finish-wrap-proc) ; takes quads in wrap, triggering quad, and wrap idx; returns list containing wrap (and maybe other things)
|
|
|
|
|
(define (wrap qs
|
|
|
|
|
[target-size (current-wrap-distance)]
|
|
|
|
|
[debug #f]
|
|
|
|
|
#:hard-break [hard-break? (λ (x) #f)]
|
|
|
|
|
#:soft-break [soft-break? (λ (x) #f)]
|
|
|
|
|
#:wrap-anywhere? [wrap-anywhere? #f]
|
|
|
|
|
#:finish-wrap [finish-wrap-proc (λ (xs q idx) (list xs))])
|
|
|
|
|
; takes quads in wrap, triggering quad, and wrap idx; returns list containing wrap (and maybe other things)
|
|
|
|
|
(define (finish-wrap qs wrap-idx [wrap-triggering-q (car qs)])
|
|
|
|
|
;; reverse because quads accumulated in reverse
|
|
|
|
|
;; wrap-triggering-q is ordinarily the last accumulated q
|
|
|
|
@ -64,10 +38,23 @@
|
|
|
|
|
[current-dist #false] ; #false (to indicate start) or integer
|
|
|
|
|
[qs qs]) ; list of quads
|
|
|
|
|
(match qs
|
|
|
|
|
[(== empty) (define last-wrap (finish-wrap (wrap-append next-wrap-tail next-wrap-head) wrap-idx #f))
|
|
|
|
|
; append* because `finish-wrap-proc` returns a spliceable list
|
|
|
|
|
; reverse because wraps accumulated in reverse
|
|
|
|
|
(append* (reverse (cons last-wrap wraps)))]
|
|
|
|
|
[(or (list (? hard-break?)) (== empty))
|
|
|
|
|
(define last-wrap (finish-wrap (wrap-append next-wrap-tail next-wrap-head) wrap-idx #f))
|
|
|
|
|
; append* because `finish-wrap-proc` returns a spliceable list
|
|
|
|
|
; reverse because wraps accumulated in reverse
|
|
|
|
|
(match (append* (reverse (cons last-wrap wraps)))
|
|
|
|
|
[(list (list)) (list)]
|
|
|
|
|
[val val])]
|
|
|
|
|
[(cons (? hard-break? hard-break-q) other-qs)
|
|
|
|
|
(debug-report 'hard-break)
|
|
|
|
|
;; a break is inevitable but we want to wait to finish the wrap until we see a hard quad
|
|
|
|
|
;; but we can move the current-partial into the current-wrap
|
|
|
|
|
(loop wraps
|
|
|
|
|
wrap-idx
|
|
|
|
|
(wrap-append (cons hard-break-q next-wrap-tail) next-wrap-head)
|
|
|
|
|
null
|
|
|
|
|
current-dist
|
|
|
|
|
other-qs)]
|
|
|
|
|
[(cons q other-qs)
|
|
|
|
|
(debug-report q 'next-q)
|
|
|
|
|
(debug-report (quad-elems q) 'next-q-elems)
|
|
|
|
@ -243,9 +230,9 @@
|
|
|
|
|
(module+ test
|
|
|
|
|
(test-case
|
|
|
|
|
"soft hyphens"
|
|
|
|
|
(check-equal? (linewrap (list shy) 1) (list (list)))
|
|
|
|
|
(check-equal? (linewrap (list shy shy) 2) (list (list)))
|
|
|
|
|
(check-equal? (linewrap (list shy shy shy) 2) (list (list)))
|
|
|
|
|
(check-equal? (linewrap (list shy) 1) (list))
|
|
|
|
|
(check-equal? (linewrap (list shy shy) 2) (list))
|
|
|
|
|
(check-equal? (linewrap (list shy shy shy) 2) (list))
|
|
|
|
|
(check-equal? (linewrap (list x shy) 1) (list (list x)))
|
|
|
|
|
(check-equal? (linewrap (list x shy shy shy shy) 1) (list (list x)))
|
|
|
|
|
;; todo: degenerate cases that don't work without continuations
|
|
|
|
@ -350,14 +337,14 @@
|
|
|
|
|
(check-equal? (pagewrap (list x pbr pbr x x) 2) (list (list x) pbr (list) pbr (list x x)))
|
|
|
|
|
(check-equal? (pagewrap (list lbr x lbr lbr pbr lbr x x lbr) 2) (list (list x) pbr (list x x)))))
|
|
|
|
|
|
|
|
|
|
(module+ test
|
|
|
|
|
(test-case
|
|
|
|
|
"composed line breaks and page breaks"
|
|
|
|
|
(check-equal? (pagewrap (linewrap null 1) 2) (list))
|
|
|
|
|
(check-equal? (pagewrap (linewrap (list x) 1) 2) (list (list x)))
|
|
|
|
|
(check-equal? (pagewrap (linewrap (list x x x) 1) 2) (list (list x lbr x) pbr (list x)))
|
|
|
|
|
(check-equal? (pagewrap (linewrap (list x x x) 2) 2) (list (list x x) pbr (list x)))
|
|
|
|
|
(check-equal? (pagewrap (linewrap (list x x x) 2) 1) (list (list x) pbr (list x) pbr (list x)))))
|
|
|
|
|
#;(module+ test
|
|
|
|
|
(test-case
|
|
|
|
|
"composed line breaks and page breaks"
|
|
|
|
|
(check-equal? (pagewrap (linewrap null 1) 2) (list))
|
|
|
|
|
(check-equal? (pagewrap (linewrap (list x) 1) 2) (list (list x)))
|
|
|
|
|
(check-equal? (pagewrap (linewrap (list x x x) 1) 2) (list (list x lbr x) pbr (list x)))
|
|
|
|
|
(check-equal? (pagewrap (linewrap (list x x x) 2) 2) (list (list x x) pbr (list x)))
|
|
|
|
|
(check-equal? (pagewrap (linewrap (list x x x) 2) 1) (list (list x) pbr (list x) pbr (list x)))))
|
|
|
|
|
|
|
|
|
|
(define (linewrap2 xs size [debug #f])
|
|
|
|
|
(add-between
|
|
|
|
|