Scribble: clean up text-mode output
- line-flow paragraphs to fit in 72 columns - better indentation for itemizations - format tables with paragraphs and nested tables original commit: 60c4acb094286e2501bdfc40a6bec2fd86faee4f
This commit is contained in:
parent
ce1101a292
commit
80991752ea
|
@ -1,9 +1,30 @@
|
|||
|
||||
(module text-render mzscheme
|
||||
(module text-render racket/base
|
||||
(require "core.ss"
|
||||
mzlib/class)
|
||||
racket/class
|
||||
racket/port)
|
||||
(provide render-mixin)
|
||||
|
||||
(define current-preserve-spaces (make-parameter #f))
|
||||
|
||||
(define current-indent (make-parameter 0))
|
||||
(define (make-indent amt)
|
||||
(+ amt (current-indent)))
|
||||
(define (indent)
|
||||
(let ([i (current-indent)])
|
||||
(unless (zero? i)
|
||||
(display (make-string i #\space)))))
|
||||
(define (indented-newline)
|
||||
(newline)
|
||||
(indent))
|
||||
|
||||
(define indent-pxs (make-hash))
|
||||
(define (indent->paragraph-px amt)
|
||||
(or (hash-ref indent-pxs amt #f)
|
||||
(let ([px (pregexp (format "^ *(.{1,~a}(?<! ))(?: |$)" (- 72 amt)))])
|
||||
(hash-set! indent-pxs amt px)
|
||||
px)))
|
||||
|
||||
(define (render-mixin %)
|
||||
(class %
|
||||
|
||||
|
@ -14,15 +35,10 @@
|
|||
(#rx"''" "\U201D")
|
||||
(#rx"'" "\U2019")))
|
||||
|
||||
(inherit render-content
|
||||
render-paragraph
|
||||
render-block)
|
||||
(inherit render-block)
|
||||
|
||||
(define/override (render-part d ht)
|
||||
(let ([number (collected-info-number (part-collected-info d ht))])
|
||||
(when (or (ormap values number)
|
||||
(part-title-content d))
|
||||
(newline))
|
||||
(for-each (lambda (n)
|
||||
(when n
|
||||
(printf "~s." n)))
|
||||
|
@ -33,15 +49,16 @@
|
|||
(render-content (part-title-content d) d ht))
|
||||
(when (or (ormap values number)
|
||||
(part-title-content d))
|
||||
(newline)
|
||||
(newline))
|
||||
(newline)
|
||||
(render-flow (part-blocks d) d ht #f)
|
||||
(let loop ([pos 1]
|
||||
[secs (part-parts d)])
|
||||
[secs (part-parts d)]
|
||||
[need-newline? (pair? (part-blocks d))])
|
||||
(unless (null? secs)
|
||||
(newline)
|
||||
(when need-newline? (newline))
|
||||
(render-part (car secs) ht)
|
||||
(loop (add1 pos) (cdr secs))))))
|
||||
(loop (add1 pos) (cdr secs) #t)))))
|
||||
|
||||
(define/override (render-flow f part ht starting-item?)
|
||||
(if (null? f)
|
||||
|
@ -50,26 +67,60 @@
|
|||
append
|
||||
(render-block (car f) part ht starting-item?)
|
||||
(map (lambda (p)
|
||||
(newline) (newline)
|
||||
(indented-newline)
|
||||
(render-block p part ht #f))
|
||||
(cdr f)))))
|
||||
|
||||
|
||||
(define/override (render-intrapara-block p part ri first? last? starting-item?)
|
||||
(unless first? (newline) (newline))
|
||||
(unless first? (indented-newline))
|
||||
(super render-intrapara-block p part ri first? last? starting-item?))
|
||||
|
||||
(define/override (render-table i part ht inline?)
|
||||
(let ([flowss (table-blockss i)])
|
||||
(if (null? flowss)
|
||||
null
|
||||
(apply
|
||||
append
|
||||
(map (lambda (d) (unless (eq? d 'cont) (render-block d part ht #f))) (car flowss))
|
||||
(map (lambda (flows)
|
||||
(newline)
|
||||
(map (lambda (d) (unless (eq? d 'cont) (render-block d part ht #f))) flows))
|
||||
(cdr flowss))))))
|
||||
(let* ([strs (map (lambda (flows)
|
||||
(map (lambda (d)
|
||||
(if (eq? d 'cont)
|
||||
d
|
||||
(let ([o (open-output-string)])
|
||||
(parameterize ([current-indent 0]
|
||||
[current-output-port o])
|
||||
(render-block d part ht #f))
|
||||
(regexp-split
|
||||
#rx"\n"
|
||||
(regexp-replace #rx"\n$" (get-output-string o) "")))))
|
||||
flows))
|
||||
flowss)]
|
||||
[widths (map (lambda (col)
|
||||
(for/fold ([d 0]) ([i (in-list col)])
|
||||
(if (eq? i 'cont)
|
||||
0
|
||||
(apply max d (map string-length i)))))
|
||||
(apply map list strs))])
|
||||
(for/fold ([indent? #f]) ([row (in-list strs)])
|
||||
(let ([h (apply max 0 (map length row))])
|
||||
(let ([row* (for/list ([i (in-range h)])
|
||||
(for/list ([col (in-list row)])
|
||||
(if (i . < . (length col))
|
||||
(list-ref col i)
|
||||
"")))])
|
||||
(for/fold ([indent? indent?]) ([sub-row (in-list row*)])
|
||||
(when indent? (indent))
|
||||
(for/fold ([space? #f]) ([col (in-list sub-row)]
|
||||
[w (in-list widths)])
|
||||
(when space? (display " "))
|
||||
(let ([col (if (eq? col 'cont)
|
||||
""
|
||||
col)])
|
||||
(display col)
|
||||
(display (make-string (- w (string-length col)) #\space)))
|
||||
#t)
|
||||
(newline)
|
||||
#t)))
|
||||
#t)
|
||||
null))))
|
||||
|
||||
(define/override (render-itemization i part ht)
|
||||
(let ([flows (itemization-blockss i)])
|
||||
|
@ -78,11 +129,50 @@
|
|||
(apply append
|
||||
(begin
|
||||
(printf "* ")
|
||||
(render-flow (car flows) part ht #t))
|
||||
(parameterize ([current-indent (make-indent 2)])
|
||||
(render-flow (car flows) part ht #t)))
|
||||
(map (lambda (d)
|
||||
(printf "\n\n* ")
|
||||
(render-flow d part ht #f))
|
||||
(indented-newline)
|
||||
(printf "* ")
|
||||
(parameterize ([current-indent (make-indent 2)])
|
||||
(render-flow d part ht #f)))
|
||||
(cdr flows))))))
|
||||
|
||||
(define/override (render-paragraph p part ri)
|
||||
(let ([o (open-output-string)])
|
||||
(parameterize ([current-output-port o])
|
||||
(super render-paragraph p part ri))
|
||||
(let ([i (open-input-string
|
||||
(regexp-replace* #rx"\n" (get-output-string o) " "))]
|
||||
[px (indent->paragraph-px (current-indent))])
|
||||
(let loop ([indent? #f])
|
||||
(cond
|
||||
[(or (regexp-try-match px i)
|
||||
(regexp-try-match #px"^ *(.+(?<! ))(?: |$)" i))
|
||||
=> (lambda (m)
|
||||
(when indent? (indent))
|
||||
(write-bytes (cadr m))
|
||||
(newline)
|
||||
(loop #t))]
|
||||
[else
|
||||
(regexp-try-match "^ +" i)
|
||||
(let ([b (read-byte i)])
|
||||
(unless (eof-object? b)
|
||||
(when indent? (indent))
|
||||
(write-byte b)
|
||||
(copy-port i (current-output-port))
|
||||
(newline)))])))
|
||||
null))
|
||||
|
||||
(define/override (render-content i part ri)
|
||||
(if (and (element? i)
|
||||
(let ([s (element-style i)])
|
||||
(or (eq? 'hspace s)
|
||||
(and (style? s)
|
||||
(eq? 'hspace (style-name s))))))
|
||||
(parameterize ([current-preserve-spaces #t])
|
||||
(super render-content i part ri))
|
||||
(super render-content i part ri)))
|
||||
|
||||
(define/override (render-other i part ht)
|
||||
(cond
|
||||
|
@ -96,12 +186,14 @@
|
|||
[(lang) ">"]
|
||||
[(rang) "<"]
|
||||
[(rarr) "->"]
|
||||
[(nbsp) " "]
|
||||
[(nbsp) "\uA0"]
|
||||
[(prime) "'"]
|
||||
[(alpha) "\u03B1"]
|
||||
[(infin) "\u221E"]
|
||||
[else (error 'text-render "unknown element symbol: ~e" i)]))]
|
||||
[(string? i) (display i)]
|
||||
[(string? i) (if (current-preserve-spaces)
|
||||
(display (regexp-replace* #rx" " i "\uA0"))
|
||||
(display i))]
|
||||
[else (write i)])
|
||||
null)
|
||||
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
|
||||
(Felleisen et al. 2010)
|
||||
(Felleisen et al. 2010, part I)
|
||||
(Felleisen et al. 2010, part II)
|
||||
(Felleisen et al. 2010)
|
||||
(Felleisen et al. 2010) (Felleisen et al. 2010, part I) (Felleisen et
|
||||
al. 2010, part II) (Felleisen et al. 2010)
|
||||
|
||||
Bibliography
|
||||
|
||||
Matthias Felleisen, Robert Bruce Findler, and Matthew Flatt. Semantics Engineering with PLT Redex. MIT Press, 2010.
|
||||
Matthias Felleisen, Robert Bruce Findler, and Matthew Flatt. Semantics
|
||||
Engineering with PLT Redex. MIT Press, 2010.
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
|
||||
quote
|
||||
|
||||
@itemlist[#:style 'ordered
|
||||
@item{Eat cookie.}]
|
||||
@itemlist[#:style 'ordered
|
||||
@item{Eat cookie.}]
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
Example:
|
||||
> #f
|
||||
#f
|
||||
> #f
|
||||
#f
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
|
||||
Pretty-Print-Handler Bug Example
|
||||
|
||||
Example:
|
||||
> '((x "positional 1")
|
||||
(rest ("positional 2" "positional 3"))
|
||||
(a ())
|
||||
(b ("b-arg"))
|
||||
(c (("first c1" "second c1") ("first c2" "second c2")))
|
||||
(d #f)
|
||||
(e ()))
|
||||
'((x "positional 1")
|
||||
(rest ("positional 2" "positional 3"))
|
||||
(a ())
|
||||
(b ("b-arg"))
|
||||
(c (("first c1" "second c1") ("first c2" "second c2")))
|
||||
(d #f)
|
||||
(e ()))
|
||||
Example:
|
||||
> '((x "positional 1")
|
||||
(rest ("positional 2" "positional 3"))
|
||||
(a ())
|
||||
(b ("b-arg"))
|
||||
(c (("first c1" "second c1") ("first c2" "second c2")))
|
||||
(d #f)
|
||||
(e ()))
|
||||
'((x "positional 1")
|
||||
(rest ("positional 2" "positional 3"))
|
||||
(a ())
|
||||
(b ("b-arg"))
|
||||
(c (("first c1" "second c1") ("first c2" "second c2")))
|
||||
(d #f)
|
||||
(e ()))
|
||||
|
|
76
collects/tests/scribble/docs/text.scrbl
Normal file
76
collects/tests/scribble/docs/text.scrbl
Normal file
|
@ -0,0 +1,76 @@
|
|||
#lang scribble/manual
|
||||
@(require (for-label racket/base))
|
||||
|
||||
@title{Document}
|
||||
|
||||
This document exercises various constructs to check text output.
|
||||
|
||||
@section{Part A}
|
||||
|
||||
Scribble is a collection of tools for creating prose documents---papers, books, library documentation, etc.---in HTML or PDF (via Latex)
|
||||
form. More generally, Scribble helps you
|
||||
write programs that are rich
|
||||
in textual content, whether the content is prose to be typeset or any
|
||||
other form of text to be generated
|
||||
programmatically.
|
||||
|
||||
@subsection{A Subsection}
|
||||
|
||||
Here's some Racket code:
|
||||
|
||||
@racketblock[
|
||||
(define half (lambda (x)
|
||||
(x x)))
|
||||
(x x)
|
||||
]
|
||||
|
||||
@subsection{Another Subsection}
|
||||
|
||||
@defmodule[racket/base]
|
||||
|
||||
@defproc[(cons [car (or/c #f
|
||||
other?)]
|
||||
[cdr any?])
|
||||
stuff?]{
|
||||
|
||||
Ok?}
|
||||
|
||||
@section{B}
|
||||
|
||||
@itemlist[
|
||||
|
||||
@item{Run
|
||||
@commandline{scribble --pdf mouse.scrbl}
|
||||
to generate PDF as @filepath{mouse.pdf}. This will
|
||||
work only if you have @exec{pdflatex} installed.
|
||||
If you'd like to see the intermediate Latex, try
|
||||
@commandline{scribble --latex mouse.scrbl}
|
||||
to generate @filepath{mouse.tex}.}
|
||||
|
||||
@item{Run
|
||||
@commandline{scribble --html mouse.scrbl}
|
||||
to generate HTML as @filepath{mouse.html}. You may
|
||||
notice that the apostrophe in ``he's'' turned into a
|
||||
curly apostrophe.}
|
||||
|
||||
@item{Run
|
||||
@commandline{scribble --htmls mouse.scrbl}
|
||||
to generate HTML as @filepath{mouse/index.html}.
|
||||
Sub-sections (which we add next) will appear as separate
|
||||
HTML files in the @filepath{mouse} directory.}
|
||||
|
||||
]
|
||||
|
||||
Run the @exec{scribble} command(s) from the old section
|
||||
again. You may notice the curly double-quotes in the output, and
|
||||
the @litchar{---} turned into an em dash.
|
||||
|
||||
@section{C}
|
||||
|
||||
@subsection{Inside C}
|
||||
|
||||
Section C had no text before its subsections.
|
||||
|
||||
@subsection{Inside C, Again}
|
||||
|
||||
But the subsections have text.
|
71
collects/tests/scribble/docs/text.txt
Normal file
71
collects/tests/scribble/docs/text.txt
Normal file
|
@ -0,0 +1,71 @@
|
|||
Document
|
||||
|
||||
This document exercises various constructs to check text output.
|
||||
|
||||
1. Part A
|
||||
|
||||
Scribble is a collection of tools for creating prose documents—papers,
|
||||
books, library documentation, etc.—in HTML or PDF (via Latex) form. More
|
||||
generally, Scribble helps you write programs that are rich in textual
|
||||
content, whether the content is prose to be typeset or any other form of
|
||||
text to be generated programmatically.
|
||||
|
||||
1.1. A Subsection
|
||||
|
||||
Here’s some Racket code:
|
||||
|
||||
(define half (lambda (x)
|
||||
(x x)))
|
||||
(x x)
|
||||
|
||||
1.2. Another Subsection
|
||||
|
||||
(require racket/base)
|
||||
|
||||
(cons car cdr) -> stuff?
|
||||
car : (or/c #f
|
||||
other?)
|
||||
cdr : any?
|
||||
|
||||
Ok?
|
||||
|
||||
2. B
|
||||
|
||||
* Run
|
||||
|
||||
scribble --pdf mouse.scrbl
|
||||
|
||||
to generate PDF as "mouse.pdf". This will work only if you have
|
||||
pdflatex installed. If you’d like to see the intermediate Latex, try
|
||||
|
||||
scribble --latex mouse.scrbl
|
||||
|
||||
to generate "mouse.tex".
|
||||
|
||||
* Run
|
||||
|
||||
scribble --html mouse.scrbl
|
||||
|
||||
to generate HTML as "mouse.html". You may notice that the apostrophe
|
||||
in “he’s” turned into a curly apostrophe.
|
||||
|
||||
* Run
|
||||
|
||||
scribble --htmls mouse.scrbl
|
||||
|
||||
to generate HTML as "mouse/index.html". Sub-sections (which we add
|
||||
next) will appear as separate HTML files in the "mouse" directory.
|
||||
|
||||
Run the scribble command(s) from the old section again. You may notice
|
||||
the curly double-quotes in the output, and the --- turned into an em
|
||||
dash.
|
||||
|
||||
3. C
|
||||
|
||||
3.1. Inside C
|
||||
|
||||
Section C had no text before its subsections.
|
||||
|
||||
3.2. Inside C, Again
|
||||
|
||||
But the subsections have text.
|
Loading…
Reference in New Issue
Block a user