sun eve
parent
ec7aa4fa43
commit
b9439d96fc
@ -0,0 +1,38 @@
|
||||
#lang racket/base
|
||||
(require racket/date)
|
||||
(require racket/string)
|
||||
(require racket/format)
|
||||
|
||||
(require "readability.rkt")
|
||||
|
||||
(provide (all-defined-out))
|
||||
|
||||
; todo: contracts, tests, docs
|
||||
|
||||
; debug utilities
|
||||
(define (message . items)
|
||||
(define (zero-fill str count)
|
||||
(set! str (~a str))
|
||||
(if (> (string-length str) count)
|
||||
str
|
||||
(string-append (make-string (- count (string-length str)) #\0) str)))
|
||||
|
||||
(define (make-date-string)
|
||||
(define date (current-date))
|
||||
(define date-fields (map (λ(x) (zero-fill x 2))
|
||||
(list (date-month date)
|
||||
(date-day date)
|
||||
(date-year date)
|
||||
(modulo (date-hour date) 12)
|
||||
(date-minute date)
|
||||
(date-second date)
|
||||
(if (< (date-hour date) 12) "am" "pm"))))
|
||||
(apply format "[~a.~a.~a ~a:~a:~a~a]" date-fields))
|
||||
(displayln (string-join `(,(make-date-string) ,@(map (λ(x)(if (string? x) x (~v x))) items))) (current-error-port)))
|
||||
|
||||
|
||||
; report the current value of the variable, then return it
|
||||
(define-syntax-rule (report var)
|
||||
(begin
|
||||
(message 'var "=" var)
|
||||
var))
|
@ -0,0 +1,88 @@
|
||||
#lang racket/base
|
||||
(require racket/contract)
|
||||
(require racket/list)
|
||||
(require racket/string)
|
||||
|
||||
(module+ test (require rackunit))
|
||||
|
||||
(require "tools.rkt")
|
||||
(provide (all-defined-out))
|
||||
|
||||
;; Find adjacent newline characters in a list and merge them into one item
|
||||
;; Scribble, by default, makes each newline a separate list item
|
||||
;; In practice, this is worthless.
|
||||
(define/contract (merge-newlines x)
|
||||
(list? . -> . list?)
|
||||
(define (newline? x)
|
||||
(and (string? x) (equal? "\n" x)))
|
||||
(define (not-newline? x)
|
||||
(not (newline? x)))
|
||||
|
||||
(define (really-merge-newlines xs [acc '()])
|
||||
(if (empty? xs)
|
||||
acc
|
||||
;; Try to peel the newlines off the front.
|
||||
(let-values ([(leading-newlines remainder) (splitf-at xs newline?)])
|
||||
(if (not (empty? leading-newlines)) ; if you got newlines ...
|
||||
;; combine them into a string and append them to the accumulator,
|
||||
;; and recurse on the rest
|
||||
(really-merge-newlines remainder (append acc (list (string-join leading-newlines ""))))
|
||||
;; otherwise peel off elements up to the next newline, append them to accumulator,
|
||||
;; and recurse on the rest
|
||||
(really-merge-newlines (dropf remainder not-newline?)
|
||||
(append acc (takef remainder not-newline?)))))))
|
||||
|
||||
(cond
|
||||
[(list? x) (really-merge-newlines (map merge-newlines x))]
|
||||
[else x]))
|
||||
|
||||
(module+ test
|
||||
(check-equal? (merge-newlines '(p "\n" "foo" "\n" "\n" "bar" (em "\n" "\n" "\n")))
|
||||
'(p "\n" "foo" "\n\n" "bar" (em "\n\n\n"))))
|
||||
|
||||
|
||||
; Mon Aug 5: start here
|
||||
|
||||
; A block-xexpr is a named expression that's not on the inline list
|
||||
; todo: bear in mind that browsers take the opposite view:
|
||||
; that only elements on the block list are blocks
|
||||
; and otherwise are treated as inline
|
||||
(define (block-xexpr? x)
|
||||
(and (named-xexpr? x) (not (in? inline-tags (car x)))))
|
||||
|
||||
|
||||
|
||||
; default content decoder for pollen
|
||||
(define/contract (decode x)
|
||||
(named-xexpr? . -> . named-xexpr?)
|
||||
|
||||
(define (&decode x)
|
||||
(cond
|
||||
[(named-xexpr? x)
|
||||
(let-values([(name attr content) (break-named-xexpr x)])
|
||||
(define decoded-x (make-named-xexpr name attr (&decode content)))
|
||||
(if (block-xexpr? decoded-x)
|
||||
; add nonbreaking-last-space to the next line when ready
|
||||
(wrap-hanging-quotes (nonbreaking-last-space decoded-x)) ; do special processing for block xexprs
|
||||
decoded-x))]
|
||||
[(xexpr-content? x) ; a list of xexprs
|
||||
(let ([x (prep-paragraph-flow x)])
|
||||
(map &decode (if (any paragraph-break? x) ; need this condition to prevent infinite recursion
|
||||
(map wrap-paragraph (splitf-at* x paragraph-break?)) ; split into ¶¶
|
||||
x)))]
|
||||
[(string? x) (typogrify x)]
|
||||
[else x]))
|
||||
|
||||
(define (stringify x) ; convert numbers to strings
|
||||
(cond
|
||||
[(list? x) (map stringify x)]
|
||||
[(number? x) (~a x)]
|
||||
[else x]))
|
||||
|
||||
(let* ([x (stringify x)]
|
||||
[x (trim-whitespace x)])
|
||||
(if (named-xexpr? x)
|
||||
(&decode x)
|
||||
;todo: improve this error message, more specific location
|
||||
; now, it just spits out the whole defective content
|
||||
(error (format "decode: ~v not a full named-xexpr" x)))))
|
@ -1,7 +1,16 @@
|
||||
#lang racket/base
|
||||
(require racket/contract)
|
||||
(require (planet mb/pollen/tools) (planet mb/pollen/decode))
|
||||
|
||||
(provide (all-defined-out))
|
||||
|
||||
(define foo "bar")
|
||||
(module+ test (require rackunit))
|
||||
|
||||
(define (root . items)
|
||||
(named-xexpr? . -> . named-xexpr?)
|
||||
`(root ,@(merge-newlines items)))
|
||||
|
||||
(module+ test
|
||||
(check-equal? (root "foo" "\n" "\n") '(root "foo" "\n\n")))
|
||||
|
||||
(define foo "bar")
|
Loading…
Reference in New Issue