diff --git a/quad/experimental.rkt b/quad/experimental.rkt index 64d827bf..cb8f5138 100644 --- a/quad/experimental.rkt +++ b/quad/experimental.rkt @@ -61,3 +61,13 @@ (define (calc-attrs tref) (map attr-ref-hash (filter (λ(attr) (<= (attr-ref-start attr) tref (sub1 (attr-ref-end attr)))) (current-token-attrs)))) + +(module+ main + (require rackunit) + (define ti (block '(measure 54) "Meg is " (box '(foo 42)) " ally.")) + (define-values (tokens attrs) (make-tokens-and-attrs ti)) + (current-tokens tokens) + (current-token-attrs attrs) + ;; todo: repair this test + #;(check-equal? tokens (vector #\M #\e #\g #\space #\i #\s #\space (box) #\space #\a #\l #\l #\y #\.)) + (check-equal? attrs '(#(#hash((measure . 54)) 0 14) #(#hash((foo . 42)) 7 8)))) \ No newline at end of file diff --git a/quad/quads-typed.rkt b/quad/quads-typed.rkt index 734c0278..8a9d0ecc 100644 --- a/quad/quads-typed.rkt +++ b/quad/quads-typed.rkt @@ -7,7 +7,7 @@ [flatten ((Listof QuadAttr) -> QuadAttrs)]) (require/typed racket/string [string-append* ((Listof String) -> String)]) (require typed/sugar/debug typed/sugar/string typed/sugar/list typed/sugar/define) -(provide (all-defined-out)) +(provide (all-defined-out) (all-from-out "core-types.rkt")) (define-syntax-rule (even-members xs) (for/list : (Listof Any) ([(x i) (in-indexed xs)] #:when (even? i)) diff --git a/quad/quads.rkt b/quad/quads.rkt index 32578d16..a4c33b10 100644 --- a/quad/quads.rkt +++ b/quad/quads.rkt @@ -144,7 +144,7 @@ kv-pair) empty)]) (cond - [(empty? common-attrs) #f] + [(empty? common-attrs) empty] [(empty? qs) (flatten common-attrs)] [else (loop (cdr qs) (filter (λ(ca) (equal? (quad-attr-ref (car qs) (car ca) attr-missing) (cdr ca))) @@ -167,7 +167,7 @@ ;; put contract here rather than on struct, because this is the main interface ;; and this contract is more liberal. ;; but don't put a separate contract on struct, because it's superfluous. - (define/contract (id [attrs #f] . xs) + (define/contract (id [attrs empty] . xs) (() ((or/c quad-attrs? hashable-list?)) #:rest quad-list? . ->* . id?) (quad 'id (and attrs (if (hash? attrs) attrs (apply hash attrs))) xs)) ;; quad list predicate and list-of-list predicate. @@ -234,6 +234,6 @@ (define-break-type block) (define-break-type line) -(define (->input q) (input #f q)) +(define (->input q) (input empty q)) (define coerce/input? (make-coercion-contract input)) diff --git a/quad/quick-sample-typed.rkt b/quad/quick-sample-typed.rkt new file mode 100644 index 00000000..7d2adc4d --- /dev/null +++ b/quad/quick-sample-typed.rkt @@ -0,0 +1,4 @@ +#lang typed/racket/base +(require "quads-typed.rkt" racket/file racket/string racket/list racket/include typed/sugar/define) +(provide (all-defined-out)) +(include "quick-sample.rktd") \ No newline at end of file diff --git a/quad/quick-sample.rkt b/quad/quick-sample.rkt new file mode 100644 index 00000000..d19e30c9 --- /dev/null +++ b/quad/quick-sample.rkt @@ -0,0 +1,4 @@ +#lang typed/racket/base/no-check +(require "quads.rkt" racket/file racket/string racket/function racket/list racket/include) +(provide (all-defined-out)) +(include "quick-sample.rktd") \ No newline at end of file diff --git a/quad/quick-sample.rktd b/quad/quick-sample.rktd new file mode 100644 index 00000000..d3f036ae --- /dev/null +++ b/quad/quick-sample.rktd @@ -0,0 +1 @@ +(define (quick-sample) (block '(measure 240.0 font "Equity Text B" leading 16.0 vmeasure 300.0 size 13.5 x-align justify x-align-last-line left) (box '(width 15.0)) (block '() (block '(weight bold font "Equity Caps B") "Hot " (word '(size 22.0) "D") "and, My Fellow Americans.") " This " (block '(no-break #t) "is some truly") " nonsense generated from my typesetting system, which is called Quad. I’m writing this in a source file in DrRacket. When I click [Run], a PDF pops out. Not bad\u200a—\u200aand no LaTeX needed. Quad, however, does use the fancy linebreaking algorithm developed for TeX. (It also includes a faster linebreaking algorithm for when speed is more important than quality.) Of course, it can also handle " (block '(font "Triplicate C4") "different fonts,") (block '(style italic) " styles, ") (word '(size 14.0 weight bold) "and sizes-") " within the same line. As you can see, it can also justify paragraphs." (block-break) (box '(width 15.0)) (block '() "“Each horizontal row represents an OS-level thread, and the colored dots represent important events in the execution of the program (they are color-coded to distinguish one event type from another). The upper-left blue dot in the timeline represents the future’s creation. The future executes for a brief period (represented by a green bar in the second line) on thread 1, and then pauses to allow the runtime thread to perform a future-unsafe operation.") (column-break) (box '(width 15.0))(block '() "In the Racket implementation, future-unsafe operations fall into one of two categories. A blocking operation halts the evaluation of the future, and will not allow it to continue until it is touched. After the operation completes within touch, the remainder of the future’s work will be evaluated sequentially by the runtime thread. A synchronized operation also halts the future, but the runtime thread may perform the operation at any time and, once completed, the future may continue running in parallel. Memory allocation and JIT compilation are two common examples of synchronized operations." (page-break) "another page")))) \ No newline at end of file diff --git a/quad/quick-test.rkt b/quad/quick-test.rkt new file mode 100644 index 00000000..186d5dd9 --- /dev/null +++ b/quad/quick-test.rkt @@ -0,0 +1,18 @@ +#lang racket/base + +(module quick-test-typed typed/racket/base + (require "main-typed.rkt" "world-typed.rkt" "quick-sample-typed.rkt" + "render-typed.rkt" typed/racket/class) + (parameterize ([world:quality-default world:draft-quality]) + (define to (time (typeset (quick-sample)))) + (time (send (new pdf-renderer%) render-to-file to "quick-test-typed.pdf")))) + +(module quick-test-untyped racket/base + (require "main.rkt" "world.rkt" "quick-sample.rkt" + "render.rkt" racket/class) + (parameterize ([world:quality-default world:draft-quality]) + (define to (time (typeset (quick-sample)))) + (time (send (new pdf-renderer%) render-to-file to "quick-test-untyped.pdf")))) + +(require 'quick-test-typed) +(require 'quick-test-untyped) \ No newline at end of file diff --git a/quad/samples-base.rktd b/quad/samples-base.rktd new file mode 100644 index 00000000..9fd5dd51 --- /dev/null +++ b/quad/samples-base.rktd @@ -0,0 +1,30 @@ +;(define ti (block '(measure 54.0 leading 18.0) "Meg is an ally.")) +(define (ti2) (block '(leading 10.0 measure 400.0 size 13.0 x-align left x-align-last-line left font "Equity Text B") (block '() "Foo-d" (word '(size 13.0) "og ") "and " (box) "Zu" (word-break '(nb "c" bb "k-")) "kerman’s. Instead of a circle, the result is a picture of the code that, if it were used as an expression, would produce a circle. In other words, code is not a function, but instead a " (block '(style italic) "new syntactic form") " for creating pictures; the bit between the opening " (block '(weight bold) "parenthesis") " with code is not an expression, but instead manipulated by the code syntactic form. " (word '(font "Triplicate T4" size 22.5 color "Orchid" background "Yellow") "Bangazoom!") " This helps explain what we meant in the previous section when we said that racket provides require and the function-calling syntax.") (block-break) (block '() "Libraries are not restricted to exporting values, such as functions; they can also define new syntactic forms. In this sense, Racket isn’t exactly a language at all; it’s more of an idea for how to structure a language so that you can extend it or create entirely new ones."))) + +(define (ti3) (block '(measure 54.0 leading 18.0) "Meg is an ally.")) + +(define (ti4) (block '(measure 300.0 x-align justify x-align-last-line right leading 18.0) "In this Madagascarian hoo-ha, Racket isn’t exactly a language at all")) + + +(define (ti5) (block '(measure 240.0 font "Equity Text B" leading 16.0 vmeasure 300.0 size 13.5 x-align justify x-align-last-line left) (box '(width 15.0)) (block '() (block '(weight bold font "Equity Caps B") "Hot" (word '(size 22.0) "Z") "ogs, My Fellow Americans.") " This " (block '(no-break #t) "is some truly") " bullshit generated from my typesetting system, which is called Quad. I’m writing this in a source file in DrRacket. When I click [Run], a PDF pops out. Not bad\u200a—\u200aand no LaTeX needed. Quad, however, does use the fancy linebreaking algorithm developed for TeX. (It also includes a faster linebreaking algorithm for when speed is more important than quality.) Of course, it can also handle " (block '(font "Triplicate C4") "different fonts,") (block '(style italic) " styles, ") (word '(size 14.0 weight bold) "and sizes-") " within the same line. As you can see, it can also justify paragraphs." (block-break) (box '(width 15.0)) (block '() "“Each horizontal row represents an OS-level thread, and the colored dots represent important events in the execution of the program (they are color-coded to distinguish one event type from another). The upper-left blue dot in the timeline represents the future’s creation. The future executes for a brief period (represented by a green bar in the second line) on thread 1, and then pauses to allow the runtime thread to perform a future-unsafe operation.") (column-break) (box '(width 15.0))(block '() "In the Racket implementation, future-unsafe operations fall into one of two categories. A blocking operation halts the evaluation of the future, and will not allow it to continue until it is touched. After the operation completes within touch, the remainder of the future’s work will be evaluated sequentially by the runtime thread. A synchronized operation also halts the future, but the runtime thread may perform the operation at any time and, once completed, the future may continue running in parallel. Memory allocation and JIT compilation are two common examples of synchronized operations." (page-break) "another page")))) + +(define (ti6) (block '(font "Equity Text B" measure 210.0 leading 14.0 size 20.0 x-align justify x-align-last-line left) + "Firstlinerhere" (column-break) "Secondlinerhere" (column-break) "Thirdlinerhere")) + + +(: make-sample : ((String) ((Option Integer)) . ->* . Quad)) +(define (make-sample jude-text [line-limit #f]) + (define sample-string : String + (if line-limit + (let ([lines : (Listof String) (file->lines jude-text)]) + (string-join (take lines (min line-limit (length lines))) "\n")) + (file->string jude-text))) + (define jude-blocks ((inst map String String) (λ(s) (regexp-replace* #rx"\n" s " ")) (string-split sample-string "\n\n"))) + (apply block '(font "Equity Text B" measure 360.0 leading 14.0 column-count 1 column-gutter 10.0 size 11.5 x-align justify x-align-last-line left) (add-between (map (λ([jb : String]) (block '() (box '(width 10.0)) (optical-kern) jb)) (filter (λ([jb : String]) (< 0 (string-length jb))) jude-blocks)) (block-break)))) + +(define (jude) (make-sample "texts/jude.txt")) +(define (jude0) (make-sample "texts/jude0.txt")) +(define (judebig) (make-sample "texts/judebig.txt")) +(define (segfault) (make-sample "texts/segfault.txt")) + +(define (jude1) (block '(font "Equity Text B" measure 150.0 leading 14.0 column-count 4 size 11.0 x-align justify x-align-last-line left) "this—is—a—test—of—em—dashes—breakable—or—not?")) \ No newline at end of file diff --git a/quad/samples-typed.rkt b/quad/samples-typed.rkt index b6c4cd8f..96af98c6 100644 --- a/quad/samples-typed.rkt +++ b/quad/samples-typed.rkt @@ -1,34 +1,4 @@ #lang typed/racket/base -(require "quads-typed.rkt" "core-types.rkt" racket/file racket/string racket/list typed/sugar/define) +(require "quads-typed.rkt" racket/file racket/string racket/list racket/include typed/sugar/define) (provide (all-defined-out)) - -;(define ti (block '(measure 54.0 leading 18.0) "Meg is an ally.")) -(define (ti2) (block '(leading 10.0 measure 400.0 size 13.0 x-align left x-align-last-line left font "Equity Text B") (block '() "Foo-d" (word '(size 13.0) "og ") "and " (box) "Zu" (word-break '(nb "c" bb "k-")) "kerman’s. Instead of a circle, the result is a picture of the code that, if it were used as an expression, would produce a circle. In other words, code is not a function, but instead a " (block '(style italic) "new syntactic form") " for creating pictures; the bit between the opening " (block '(weight bold) "parenthesis") " with code is not an expression, but instead manipulated by the code syntactic form. " (word '(font "Triplicate T4" size 22.5 color "Orchid" background "Yellow") "Bangazoom!") " This helps explain what we meant in the previous section when we said that racket provides require and the function-calling syntax.") (block-break) (block '() "Libraries are not restricted to exporting values, such as functions; they can also define new syntactic forms. In this sense, Racket isn’t exactly a language at all; it’s more of an idea for how to structure a language so that you can extend it or create entirely new ones."))) - -(define (ti3) (block '(measure 54.0 leading 18.0) "Meg is an ally.")) - -(define (ti4) (block '(measure 300.0 x-align justify x-align-last-line right leading 18.0) "In this Madagascarian hoo-ha, Racket isn’t exactly a language at all")) - - -(define (ti5) (block '(measure 240.0 font "Equity Text B" leading 16.0 vmeasure 300.0 size 13.5 x-align justify x-align-last-line left) (box '(width 15.0)) (block '() (block '(weight bold font "Equity Caps B") "Hot" (word '(size 22.0) "Z") "ogs, My Fellow Americans.") " This " (block '(no-break #t) "is some truly") " bullshit generated from my typesetting system, which is called Quad. I’m writing this in a source file in DrRacket. When I click [Run], a PDF pops out. Not bad\u200a—\u200aand no LaTeX needed. Quad, however, does use the fancy linebreaking algorithm developed for TeX. (It also includes a faster linebreaking algorithm for when speed is more important than quality.) Of course, it can also handle " (block '(font "Triplicate C4") "different fonts,") (block '(style italic) " styles, ") (word '(size 14.0 weight bold) "and sizes-") " within the same line. As you can see, it can also justify paragraphs." (block-break) (box '(width 15.0)) (block '() "“Each horizontal row represents an OS-level thread, and the colored dots represent important events in the execution of the program (they are color-coded to distinguish one event type from another). The upper-left blue dot in the timeline represents the future’s creation. The future executes for a brief period (represented by a green bar in the second line) on thread 1, and then pauses to allow the runtime thread to perform a future-unsafe operation.") (column-break) (box '(width 15.0))(block '() "In the Racket implementation, future-unsafe operations fall into one of two categories. A blocking operation halts the evaluation of the future, and will not allow it to continue until it is touched. After the operation completes within touch, the remainder of the future’s work will be evaluated sequentially by the runtime thread. A synchronized operation also halts the future, but the runtime thread may perform the operation at any time and, once completed, the future may continue running in parallel. Memory allocation and JIT compilation are two common examples of synchronized operations." (page-break) "another page")))) - -(define (ti6) (block '(font "Equity Text B" measure 210.0 leading 14.0 size 20.0 x-align justify x-align-last-line left) - "Firstlinerhere" (column-break) "Secondlinerhere" (column-break) "Thirdlinerhere")) - - -(define/typed (make-sample jude-text [line-limit #f]) - ((String) ((Option Integer)) . ->* . Quad) - (define sample-string : String - (if line-limit - (let ([lines : (Listof String) (file->lines jude-text)]) - (string-join (take lines (min line-limit (length lines))) "\n")) - (file->string jude-text))) - (define jude-blocks ((inst map String String) (λ(s) (regexp-replace* #rx"\n" s " ")) (string-split sample-string "\n\n"))) - (apply block '(font "Equity Text B" measure 360.0 leading 14.0 column-count 1 column-gutter 10.0 size 11.5 x-align justify x-align-last-line left) (add-between (map (λ([jb : String]) (block '() (box '(width 10.0)) (optical-kern) jb)) (filter (λ([jb : String]) (< 0 (string-length jb))) jude-blocks)) (block-break)))) - -(define (jude) (make-sample "texts/jude.txt")) -(define (jude0) (make-sample "texts/jude0.txt")) -(define (judebig) (make-sample "texts/judebig.txt")) -(define (segfault) (make-sample "texts/segfault.txt")) - -(define (jude1) (block '(font "Equity Text B" measure 150.0 leading 14.0 column-count 4 size 11.0 x-align justify x-align-last-line left) "this—is—a—test—of—em—dashes—breakable—or—not?")) \ No newline at end of file +(include "samples-base.rktd") \ No newline at end of file diff --git a/quad/samples.rkt b/quad/samples.rkt index 5281f1f2..adbee5db 100644 --- a/quad/samples.rkt +++ b/quad/samples.rkt @@ -1,32 +1,4 @@ -#lang racket/base -(require "quads.rkt" racket/file racket/string racket/function racket/list) +#lang typed/racket/base/no-check +(require "quads.rkt" racket/file racket/string racket/function racket/list racket/include) (provide (all-defined-out)) - -;(define ti (block '(measure 54 leading 18) "Meg is an ally.")) -(define (ti2) (block '(leading 10 measure 400 size 13 x-align left x-align-last-line left font "Equity Text B") (block #f "Foo-d" (word '(size 13) "og ") "and " (box) "Zu" (word-break '(nb "c" bb "k-")) "kerman’s. Instead of a circle, the result is a picture of the code that, if it were used as an expression, would produce a circle. In other words, code is not a function, but instead a " (block '(style italic) "new syntactic form") " for creating pictures; the bit between the opening " (block '(weight bold) "parenthesis") " with code is not an expression, but instead manipulated by the code syntactic form. " (word '(font "Triplicate T4" size 22.5 color "Orchid" background "Yellow") "Bangazoom!") " This helps explain what we meant in the previous section when we said that racket provides require and the function-calling syntax.") (block-break) (block #f "Libraries are not restricted to exporting values, such as functions; they can also define new syntactic forms. In this sense, Racket isn’t exactly a language at all; it’s more of an idea for how to structure a language so that you can extend it or create entirely new ones."))) - -(define (ti3) (block '(measure 54 leading 18) "Meg is an ally.")) - -(define (ti4) (block '(measure 300 x-align justify x-align-last-line right leading 18) "In this Madagascarian hoo-ha, Racket isn’t exactly a language at all")) - - -(define (ti5) (block '(measure 240 font "Equity Text B" leading 16 vmeasure 300 size 13.5 x-align justify x-align-last-line left) (box '(width 15)) (block #f (block '(weight bold font "Equity Caps B") "Hot" (word '(size 22) "Z") "ogs, My Fellow Americans.") " This " (block '(no-break #t) "is some truly") " bullshit generated from my typesetting system, which is called Quad. I’m writing this in a source file in DrRacket. When I click [Run], a PDF pops out. Not bad\u200a—\u200aand no LaTeX needed. Quad, however, does use the fancy linebreaking algorithm developed for TeX. (It also includes a faster linebreaking algorithm for when speed is more important than quality.) Of course, it can also handle " (block '(font "Triplicate C4") "different fonts,") (block '(style italic) " styles, ") (word '(size 14 weight bold) "and sizes-") " within the same line. As you can see, it can also justify paragraphs." (block-break) (box '(width 15)) (block #f "“Each horizontal row represents an OS-level thread, and the colored dots represent important events in the execution of the program (they are color-coded to distinguish one event type from another). The upper-left blue dot in the timeline represents the future’s creation. The future executes for a brief period (represented by a green bar in the second line) on thread 1, and then pauses to allow the runtime thread to perform a future-unsafe operation.") (column-break) (box '(width 15))(block #f "In the Racket implementation, future-unsafe operations fall into one of two categories. A blocking operation halts the evaluation of the future, and will not allow it to continue until it is touched. After the operation completes within touch, the remainder of the future’s work will be evaluated sequentially by the runtime thread. A synchronized operation also halts the future, but the runtime thread may perform the operation at any time and, once completed, the future may continue running in parallel. Memory allocation and JIT compilation are two common examples of synchronized operations." (page-break) "another page")))) - -(define (ti6) (block '(font "Equity Text B" measure 210 leading 14 size 20 x-align justify x-align-last-line left) - "Firstlinerhere" (column-break) "Secondlinerhere" (column-break) "Thirdlinerhere")) - - -(define (make-sample jude-text [line-limit #f]) - (define sample-string (if line-limit - (let ([lines (file->lines jude-text)]) - (string-join (take lines (min line-limit (length lines))) "\n")) - (file->string jude-text))) - (define jude-blocks (map (λ(s) (regexp-replace* #rx"\n" s " ")) (string-split sample-string "\n\n"))) - (apply block '(font "Equity Text B" measure 360 leading 14 column-count 1 column-gutter 10 size 11.5 x-align justify x-align-last-line left) (add-between (map (λ(jb) (block #f (box '(width 10)) (optical-kern) jb)) (filter (λ(jb) (< 0 (string-length jb))) jude-blocks)) (block-break)))) - -(define (jude) (make-sample "texts/jude.txt")) -(define (jude0) (make-sample "texts/jude0.txt")) -(define (judebig) (make-sample "texts/judebig.txt")) -(define (segfault) (make-sample "texts/segfault.txt")) - -(define (jude1) (block '(font "Equity Text B" measure 150 leading 14 column-count 4 size 11 x-align justify x-align-last-line left) "this—is—a—test—of—em—dashes—breakable—or—not?")) \ No newline at end of file +(include "samples-base.rktd") \ No newline at end of file diff --git a/quad/tests.rkt b/quad/tests.rkt index e94cf5d3..16d291bc 100644 --- a/quad/tests.rkt +++ b/quad/tests.rkt @@ -2,7 +2,7 @@ (require "utils.rkt" "wrap.rkt" "quads.rkt" "world.rkt" racket/list racket/format) (require rackunit) -(check-equal? (join-attrs (list (box '(width 10)) (box #f "foobar") (hash 'x 10) (list 'width 20))) +(check-equal? (join-attrs (list (box '(width 10)) (box '() "foobar") (hash 'x 10) (list 'width 20))) (list (cons 'width 10) (cons 'x 10) (cons 'width 20))) (check-equal? (flatten-attrs (hash 'foo 'bar) (hash 'x 10)) (apply hash '(foo bar x 10))) @@ -10,14 +10,14 @@ (check-equal? (merge-attrs (hash 'x -5) (hash 'x 10)) (apply hash '(x 10))) (check-equal? (gather-common-attrs (list (box '(foo bar)) (box '(foo bar goo bar zam zino)) (box '(foo bar)))) '(foo bar)) -(check-equal? (gather-common-attrs (list (box) (box '(foo bar goo bar zam zino)) (box '(foo bar)))) #f) -(check-equal? (gather-common-attrs (list (box '(width bar)) (box '(width bar)) (box '(width bar)))) #f) +(check-equal? (gather-common-attrs (list (box) (box '(foo bar goo bar zam zino)) (box '(foo bar)))) '()) +(check-equal? (gather-common-attrs (list (box '(width bar)) (box '(width bar)) (box '(width bar)))) '()) (define b1 (box '(x 10) "1st" (box '(foo bar) "2nd") "3rd")) (define b1-flattened (list (box '(x 10) "1st") (box '(x 10 foo bar) "2nd") (box '(x 10) "3rd"))) -(define b3 (box #f (word) (line) (page))) +(define b3 (box '() (word) (line) (page))) (check-true (sequence? b3)) ;(check-equal? (for/list ([i (in-quad b3)]) i) (list (word) (line) (page))) @@ -46,33 +46,33 @@ (check-true (quad-has-attr? (box '(foo bar)) 'foo)) (check-equal? (quad-attr-set (box '(foo bar)) 'foo 'zam) (box '(foo zam))) -(check-equal? (quad-attr-set (box #f) 'foo 'zam) (box '(foo zam))) -(check-equal? (quad-attr-set* (box #f) 'foo 'zam 'bar 'boo) (box '(foo zam bar boo))) +(check-equal? (quad-attr-set (box '()) 'foo 'zam) (box '(foo zam))) +(check-equal? (quad-attr-set* (box '()) 'foo 'zam 'bar 'boo) (box '(foo zam bar boo))) (check-equal? (quad-attr-set* (box '(foo bar)) 'foo 'zam 'bar 'boo) (box '(foo zam bar boo))) (check-equal? (quad-attr-remove (box '(foo bar zim zam)) 'foo) (box '(zim zam))) -(check-equal? (quad-attr-remove (box #f) 'zim) (box)) +(check-equal? (quad-attr-remove (box '()) 'zim) (box)) (check-equal? (quad-attr-remove* (box '(foo bar zim zam ding dong)) 'foo 'ding) (box '(zim zam))) -(check-equal? (quad-attr-remove* (box #f) 'zim) (box)) +(check-equal? (quad-attr-remove* (box '()) 'zim) (box)) -(check-true (quad-ends-with? (box #f "foo") "foo")) -(check-false (quad-ends-with? (box #f "foo") "food")) -(check-false (quad-ends-with? (box #f (box #f "foo")) "food")) -(check-true (quad-ends-with? (box #f (box #f "foo")) "foo")) -(check-true (quad-ends-with? (box #f (box #f "foo")) "o")) -(check-true (quad-ends-with? (box #f (box #f (box #f (box #f (box #f "foo-"))))) "-")) +(check-true (quad-ends-with? (box '() "foo") "foo")) +(check-false (quad-ends-with? (box '() "foo") "food")) +(check-false (quad-ends-with? (box '() (box '() "foo")) "food")) +(check-true (quad-ends-with? (box '() (box '() "foo")) "foo")) +(check-true (quad-ends-with? (box '() (box '() "foo")) "o")) +(check-true (quad-ends-with? (box '() (box '() (box '() (box '() (box '() "foo-"))))) "-")) -(check-equal? (quad-append (box #f "foo") "bar") (box #f "foo" "bar")) -(check-equal? (quad-append (box #f "foo") (box #f "bar")) (box #f "foo" (box #f "bar"))) +(check-equal? (quad-append (box '() "foo") "bar") (box '() "foo" "bar")) +(check-equal? (quad-append (box '() "foo") (box '() "bar")) (box '() "foo" (box '() "bar"))) -(check-equal? (quad-last-char (box #f (box #f "foo") "food")) "d") -(check-equal? (quad-last-char (box #f (box #f "foo"))) "o") -(check-equal? (quad-last-char (box #f "foo")) "o") +(check-equal? (quad-last-char (box '() (box '() "foo") "food")) "d") +(check-equal? (quad-last-char (box '() (box '() "foo"))) "o") +(check-equal? (quad-last-char (box '() "foo")) "o") (check-false (quad-last-char (box))) -(check-equal? (quad-first-char (box #f (box #f "foo") "bar")) "f") -(check-equal? (quad-first-char (box #f (box #f "foo") "bar")) "f") -(check-equal? (quad-first-char (box #f "foo")) "f") +(check-equal? (quad-first-char (box '() (box '() "foo") "bar")) "f") +(check-equal? (quad-first-char (box '() (box '() "foo") "bar")) "f") +(check-equal? (quad-first-char (box '() "foo")) "f") (check-false (quad-first-char (box))) (check-equal? (quad->string (box '(width 100) "foo")) "foo") @@ -83,7 +83,7 @@ (check-false (whitespace? (~a #\u00A0))) (check-true (whitespace/nbsp? (~a #\u00A0))) -(check-true (whitespace/nbsp? (word #f (~a #\u00A0)))) +(check-true (whitespace/nbsp? (word '() (~a #\u00A0)))) (check-false (whitespace? (format " ~a " #\u00A0))) (check-true (whitespace/nbsp? (format " ~a " #\u00A0))) (define funny-unicode-spaces (map ~a (list #\u2000 #\u2007 #\u2009 #\u200a #\u202f))) @@ -91,13 +91,5 @@ (check-true (andmap whitespace/nbsp? funny-unicode-spaces)) -(require "experimental.rkt") -(define ti (block '(measure 54) "Meg is " (box '(foo 42)) " ally.")) -(define-values (tokens attrs) (make-tokens-and-attrs ti)) -(current-tokens tokens) -(current-token-attrs attrs) -(check-equal? tokens (vector #\M #\e #\g #\space #\i #\s #\space (box) #\space #\a #\l #\l #\y #\.)) -(check-equal? attrs '(#(#hash((measure . 54)) 0 14) #(#hash((foo . 42)) 7 8))) - (let ([world:minimum-last-line-chars 0]) - (check-equal? (map (compose1 quad-list last quad-list) (make-pieces (split-quad (block #f "Foo-dog and " (box) " mas\u00adsachu.")))) '(("o") ("g") ("d") () ("s") (".")))) + (check-equal? (map (compose1 quad-list last quad-list) (make-pieces (split-quad (block '() "Foo-dog and " (box) " mas\u00adsachu.")))) '(("o") ("g") ("d") () ("s") ("."))))