forgot to add tabular.rkt
original commit: cbd8f073a99b78364a528ea26bfa6aec604acb9e
This commit is contained in:
parent
33d69779a4
commit
d9dfcf0acb
132
collects/unstable/2d/tabular.rkt
Normal file
132
collects/unstable/2d/tabular.rkt
Normal file
|
@ -0,0 +1,132 @@
|
|||
#lang racket/base
|
||||
(require (for-syntax racket/base)
|
||||
scribble/base
|
||||
scribble/core)
|
||||
(provide 2dtabular)
|
||||
(define-syntax (2dtabular stx)
|
||||
(syntax-case stx ()
|
||||
[(_ cols rows cells ...)
|
||||
(let ()
|
||||
(define row-count (length (syntax->list #'rows)))
|
||||
(define col-count (length (syntax->list #'cols)))
|
||||
(define table (make-hash))
|
||||
(define the-sep #f)
|
||||
(define the-style #f)
|
||||
(define ignore-first-line? #f)
|
||||
(define has-keywords? #f)
|
||||
(for ([cell (in-list (syntax->list #'(cells ...)))])
|
||||
(syntax-case cell ()
|
||||
[[(coord ...) body ...]
|
||||
(let ()
|
||||
(define coords
|
||||
(sort
|
||||
(for/list ([coord (in-list (syntax->list #'(coord ...)))])
|
||||
(define lst (syntax->datum coord))
|
||||
(cons (car lst)
|
||||
(cadr lst)))
|
||||
<
|
||||
#:key car))
|
||||
(define bodies (syntax->list #'(body ...)))
|
||||
(unless (or (null? (cdr coords)) (apply = (map cdr coords)))
|
||||
(raise-syntax-error '2dtabular
|
||||
"cells may not span rows"
|
||||
stx
|
||||
#f
|
||||
bodies))
|
||||
(define keyword-line?
|
||||
(and (= (+ (cdr (car coords)) 1) row-count)
|
||||
(= (length coords) col-count)
|
||||
(ormap (λ (x) (keyword? (syntax-e x))) bodies)))
|
||||
(when keyword-line? (set! has-keywords? #t))
|
||||
(cond
|
||||
[keyword-line?
|
||||
;; last row, spans the entire table, contains keywords
|
||||
;; => treat as keyword arguments to tabular
|
||||
(let loop ([bodies bodies])
|
||||
(syntax-case bodies ()
|
||||
[(#:style style-arg . rest)
|
||||
(begin
|
||||
(set! the-style #'style-arg)
|
||||
(loop #'rest))]
|
||||
[(#:style)
|
||||
(raise-syntax-error '2dtabular
|
||||
"expected a style to follow the #:style keyword"
|
||||
stx
|
||||
(car bodies))]
|
||||
[(#:sep sep-arg . rest)
|
||||
(begin
|
||||
(set! the-sep #'sep-arg)
|
||||
(loop #'rest))]
|
||||
[(#:sep)
|
||||
(raise-syntax-error '2dtabular
|
||||
"expected a separator to follow the #:sep keyword"
|
||||
stx
|
||||
(car bodies))]
|
||||
[(#:ignore-first-row . rest)
|
||||
(begin (set! ignore-first-line? #t)
|
||||
(loop #'rest))]
|
||||
[() (void)]
|
||||
[(a . b)
|
||||
(cond
|
||||
[(special-comment? (syntax-e #'a))
|
||||
(loop #'b)]
|
||||
[else
|
||||
(raise-syntax-error '2dtabular
|
||||
"expected either the keyword #:style #:sep or #:ignore-first-row"
|
||||
stx
|
||||
#'a)])]))]
|
||||
[else
|
||||
(define no-comment-bodies
|
||||
(for/list ([body (in-list bodies)]
|
||||
#:unless (special-comment? (syntax-e body)))
|
||||
(when (keyword? (syntax-e body))
|
||||
(raise-syntax-error '2dtabular
|
||||
"unexpected keyword"
|
||||
stx
|
||||
body))
|
||||
body))
|
||||
(hash-set! table
|
||||
(car coords)
|
||||
#`(build-block #,@no-comment-bodies))
|
||||
(for ([coord (in-list (cdr coords))])
|
||||
(hash-set! table coord #''cont))]))]))
|
||||
#`(tabular #,@(if the-style #`(#:style #,the-style) #'())
|
||||
#,@(if the-sep #`(#:sep #,the-sep) #'())
|
||||
(list #,@(for/list ([y (in-range
|
||||
(if ignore-first-line? 1 0)
|
||||
(if has-keywords?
|
||||
(- row-count 1)
|
||||
row-count))])
|
||||
#`(list #,@(for/list ([x (in-range col-count)])
|
||||
(hash-ref table (cons x y))))))))]))
|
||||
|
||||
(define (build-block . block-or-contents)
|
||||
(define (build-block pending)
|
||||
(paragraph (style #f '()) (reverse pending)))
|
||||
|
||||
(define blocks
|
||||
(let loop ([args block-or-contents]
|
||||
[pending '()])
|
||||
(cond
|
||||
[(null? args)
|
||||
(if (null? pending)
|
||||
'()
|
||||
(list (build-block pending)))]
|
||||
[else
|
||||
(define arg (car args))
|
||||
(cond
|
||||
[(content? arg)
|
||||
(loop (cdr args) (cons arg pending))]
|
||||
[else
|
||||
(if (null? pending)
|
||||
(cons arg (loop (cdr args) '()))
|
||||
(list* (build-block pending)
|
||||
arg
|
||||
(loop (cdr args) '())))])])))
|
||||
|
||||
(nested-flow (style #f '()) blocks))
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user