From e2d2137f44ffa2439054fc81292522d23f3a9865 Mon Sep 17 00:00:00 2001 From: Sorawee Porncharoenwase Date: Sat, 6 Jan 2024 06:56:25 -0800 Subject: [PATCH] core: add itemization-ordered style property `itemization-ordered` makes it possible to start an ordered itemization at an arbitrary number. This style property is supported in all backends. Also implement ordered itemization for the Markdown and text backends (previously, all itemizations are considered unordered). --- scribble-doc/scribblings/scribble/base.scrbl | 5 +++ scribble-doc/scribblings/scribble/core.scrbl | 10 +++++ scribble-lib/scribble/base.rkt | 8 +++- scribble-lib/scribble/core.rkt | 1 + scribble-lib/scribble/html-render.rkt | 35 ++++++++++------ scribble-lib/scribble/latex-render.rkt | 12 ++++-- scribble-lib/scribble/markdown-render.rkt | 37 ++++++++++++---- scribble-lib/scribble/text-render.rkt | 26 +++++++++--- scribble-test/tests/scribble/docs/text.scrbl | 41 ++++++++++++++++++ scribble-test/tests/scribble/docs/text.txt | 42 +++++++++++++++++++ .../tests/scribble/markdown-docs/example.md | 19 ++++++++- .../scribble/markdown-docs/example.scrbl | 19 ++++++++- 12 files changed, 223 insertions(+), 32 deletions(-) diff --git a/scribble-doc/scribblings/scribble/base.scrbl b/scribble-doc/scribblings/scribble/base.scrbl index 1798c8601d..fcc6a6026a 100644 --- a/scribble-doc/scribblings/scribble/base.scrbl +++ b/scribble-doc/scribblings/scribble/base.scrbl @@ -255,6 +255,11 @@ content.} Returns @racket[#t] if @racket[v] is an item produced by @racket[item], @racket[#f] otherwise.} +@defproc[(ordered [#:start start number? 1]) style?]{ + +Constructs a @tech{style} for an @racket[itemization] to make it +an ordered itemization. @racket[start] indicates the starting number +in the ordered itemization.} @defproc[(tabular [cells (listof (listof (or/c block? content? 'cont)))] [#:style style (or/c style? string? symbol? #f) #f] diff --git a/scribble-doc/scribblings/scribble/core.scrbl b/scribble-doc/scribblings/scribble/core.scrbl index 7c25c547ac..b3f142bbd6 100644 --- a/scribble-doc/scribblings/scribble/core.scrbl +++ b/scribble-doc/scribblings/scribble/core.scrbl @@ -717,6 +717,9 @@ The following @tech{style properties} are currently recognized: @item{@indexed-racket['never-indents] --- For Latex and @tech{compound paragraphs}; see @racket[compound-paragraph].} + @item{@racket[itemization-ordered] structure --- Indicates the starting number. + This property should always be used with the @racket['ordered] style name.} + ]} @@ -1262,6 +1265,13 @@ latter case)or cell in a @racket[table].} Like @racket[color-property], but sets the background color.} +@defstruct[itemization-ordered ([start number?])]{ + +Used as a @tech{style property} for an @racket[itemization] to indicate +that the ordered itemization should start with @racket[_start]. +The associated style name @bold{must} be @racket['ordered]. +The function @racket[ordered] creates a style with +both @racket['ordered] style name and @racket[itemization-ordered] style property.} @defstruct[table-cells ([styless (listof (listof style?))])]{ diff --git a/scribble-lib/scribble/base.rkt b/scribble-lib/scribble/base.rkt index f2a3fa8b9c..f78dc6bf4c 100644 --- a/scribble-lib/scribble/base.rkt +++ b/scribble-lib/scribble/base.rkt @@ -161,7 +161,10 @@ [item (->* () () #:rest (listof pre-flow?) - item?)]) + item?)] + [ordered (->* () + (#:start exact-nonnegative-integer?) + style?)]) (provide/contract [item? (any/c . -> . boolean?)]) @@ -185,6 +188,9 @@ (define (item . str) (make-an-item (decode-flow str))) +(define (ordered #:start [start 1]) + (make-style 'ordered (list (itemization-ordered start)))) + ;; ---------------------------------------- (provide ._ .__ ~ ?- -~-) diff --git a/scribble-lib/scribble/core.rkt b/scribble-lib/scribble/core.rkt index 30a4d1a16a..6149152407 100644 --- a/scribble-lib/scribble/core.rkt +++ b/scribble-lib/scribble/core.rkt @@ -293,6 +293,7 @@ [color-property ([color (or/c string? (list/c byte? byte? byte?))])] [background-color-property ([color (or/c string? (list/c byte? byte? byte?))])] [numberer-property ([numberer numberer?] [argument any/c])] + [itemization-ordered ([start number?])] [table-columns ([styles (listof style?)])] [table-cells ([styless (listof (listof style?))])] diff --git a/scribble-lib/scribble/html-render.rkt b/scribble-lib/scribble/html-render.rkt index b155b5046a..502b30a269 100644 --- a/scribble-lib/scribble/html-render.rkt +++ b/scribble-lib/scribble/html-render.rkt @@ -167,24 +167,27 @@ (cdr l))] [else (cons (car l) (merge-styles s cls (cdr l)))])) -(define (style->attribs style [extras null]) +(define (style->attribs style [extras null] + #:transform-property [transform-property (λ (v proc) (proc v))]) + (define (default-transform-property v) + (cond + [(attributes? v) + (map (lambda (v) (list (car v) (cdr v))) (attributes-assoc v))] + [(color-property? v) + `((style ,(format "color: ~a" (color->string (color-property-color v)))))] + [(background-color-property? v) + `((style ,(format "background-color: ~a" (color->string (background-color-property-color v)))))] + [(hover-property? v) + `((title ,(hover-property-text v)))] + [else null])) + (let ([a (merge-styles #f #f (apply append extras - (map (lambda (v) - (cond - [(attributes? v) - (map (lambda (v) (list (car v) (cdr v))) (attributes-assoc v))] - [(color-property? v) - `((style ,(format "color: ~a" (color->string (color-property-color v)))))] - [(background-color-property? v) - `((style ,(format "background-color: ~a" (color->string (background-color-property-color v)))))] - [(hover-property? v) - `((title ,(hover-property-text v)))] - [else null])) + (map (λ (v) (transform-property v default-transform-property)) (style-properties style))))]) (let ([name (style-name style)]) (if (string? name) @@ -1830,7 +1833,13 @@ `((,(if (eq? 'ordered (style-name (itemization-style t))) 'ol 'ul) - (,@(style->attribs (itemization-style t)) + (,@(style->attribs (itemization-style t) + #:transform-property + (λ (v transform-property) + (cond + [(itemization-ordered? v) + `((start ,(number->string (itemization-ordered-start v))))] + [else (transform-property v)]))) ,@(if (eq? 'compact (style-name (itemization-style t))) `([class "compact"]) '())) diff --git a/scribble-lib/scribble/latex-render.rkt b/scribble-lib/scribble/latex-render.rkt index 05eb5ef6d8..507aeb98ec 100644 --- a/scribble-lib/scribble/latex-render.rkt +++ b/scribble-lib/scribble/latex-render.rkt @@ -924,7 +924,8 @@ [(b) box-mode-bottom-name])) (define/override (render-itemization t part ri) - (let* ([style-str (let ([s (style-name (itemization-style t))]) + (let* ([st (itemization-style t)] + [style-str (let ([s (style-name st)]) (if (eq? s 'compact) "compact" s))] @@ -932,8 +933,13 @@ style-str) (if (eq? 'ordered style-str) "enumerate" - "itemize"))]) - (printf "\\begin{~a}\\atItemizeStart" mode) + "itemize"))] + [ordered-option (or (for/first ([prop (in-list (style-properties st))] + #:when (itemization-ordered? prop)) + (format "\\setcounter{enumi}{~a}" + (sub1 (itemization-ordered-start prop)))) + "")]) + (printf "\\begin{~a}~a\\atItemizeStart" mode ordered-option) (for ([flow (in-list (itemization-blockss t))]) (printf "\n\n\\~a" (if (string? style-str) (format "~aItem{" style-str) diff --git a/scribble-lib/scribble/markdown-render.rkt b/scribble-lib/scribble/markdown-render.rkt index b971e4da1b..31a495a476 100644 --- a/scribble-lib/scribble/markdown-render.rkt +++ b/scribble-lib/scribble/markdown-render.rkt @@ -151,18 +151,39 @@ null) (define/override (render-itemization i part ht) + ;; make-render-marker :: style? -> (-> number?) + (define (make-render-marker st) + (case (style-name st) + [(ordered) + (define offset 0) + (define start + (or (for/first ([prop (in-list (style-properties st))] + #:when (itemization-ordered? prop)) + (itemization-ordered-start prop)) + 1)) + (λ () + (define output (format "~a) " (+ offset start))) + (set! offset (add1 offset)) + (write-string output))] + [else (λ () (write-string "* "))])) + (define render-marker (make-render-marker (itemization-style i))) (let ([flows (itemization-blockss i)]) (if (null? flows) null (append* - (begin (printf "* ") - (parameterize ([current-indent (make-indent 2)]) - (render-flow (car flows) part ht #t))) - (for/list ([d (in-list (cdr flows))]) - (indented-newline) - (printf "* ") - (parameterize ([current-indent (make-indent 2)]) - (render-flow d part ht #f))))))) + (let ([marker-size (render-marker)]) + (parameterize ([current-indent (make-indent marker-size)]) + (render-flow (car flows) part ht #t))) + (begin0 (for/list ([d (in-list (cdr flows))]) + (indented-newline) + (define marker-size (render-marker)) + (parameterize ([current-indent (make-indent marker-size)]) + (render-flow d part ht #f))) + (when (eq? 'ordered (style-name (itemization-style i))) + (indented-newline) + ;; we add this to force Markdown to reset + ;; the consecutive numbering + (display ""))))))) (define/override (render-paragraph p part ri) (define (write-note) diff --git a/scribble-lib/scribble/text-render.rkt b/scribble-lib/scribble/text-render.rkt index e524ea5f17..d338198e1d 100644 --- a/scribble-lib/scribble/text-render.rkt +++ b/scribble-lib/scribble/text-render.rkt @@ -233,17 +233,33 @@ null))) (define/override (render-itemization i part ht) + ;; make-render-marker :: style? -> (-> number?) + (define (make-render-marker st) + (case (style-name st) + [(ordered) + (define offset 0) + (define start + (or (for/first ([prop (in-list (style-properties st))] + #:when (itemization-ordered? prop)) + (itemization-ordered-start prop)) + 1)) + (λ () + (define output (format "~a) " (+ offset start))) + (set! offset (add1 offset)) + (write-string output))] + [else (λ () (write-string "* "))])) + (define render-marker (make-render-marker (itemization-style i))) (let ([flows (itemization-blockss i)]) (if (null? flows) null (append* - (begin (printf "* ") - (parameterize ([current-indent (make-indent 2)]) - (render-flow (car flows) part ht #t))) + (let ([marker-size (render-marker)]) + (parameterize ([current-indent (make-indent marker-size)]) + (render-flow (car flows) part ht #t))) (for/list ([d (in-list (cdr flows))]) (indented-newline) - (printf "* ") - (parameterize ([current-indent (make-indent 2)]) + (define marker-size (render-marker)) + (parameterize ([current-indent (make-indent marker-size)]) (render-flow d part ht #f))))))) (define/override (render-paragraph p part ri) diff --git a/scribble-test/tests/scribble/docs/text.scrbl b/scribble-test/tests/scribble/docs/text.scrbl index 443159db9d..f3957b7fad 100644 --- a/scribble-test/tests/scribble/docs/text.scrbl +++ b/scribble-test/tests/scribble/docs/text.scrbl @@ -85,6 +85,47 @@ 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. +Ordered itemization is supported, too, and it can be started at a specified number. +Here, we start at 10. + + @itemlist[ + #:style (ordered #:start 10) + + @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.} + ] + +Subsequent ordered itemization should not continue the earlier itemization. + + @itemlist[ + #:style (ordered) + + @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.} + ] + @section{C} @subsection{Inside C} diff --git a/scribble-test/tests/scribble/docs/text.txt b/scribble-test/tests/scribble/docs/text.txt index 0993933b99..e7aef61b87 100644 --- a/scribble-test/tests/scribble/docs/text.txt +++ b/scribble-test/tests/scribble/docs/text.txt @@ -74,6 +74,48 @@ 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. +Ordered itemization is supported, too, and it can be started at a +specified number. Here, we start at 10. + +10) 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". + +11) 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. + +Subsequent ordered itemization should not continue the earlier +itemization. + +1) 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". + +2) 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. + 3. C 3.1. Inside C diff --git a/scribble-test/tests/scribble/markdown-docs/example.md b/scribble-test/tests/scribble/markdown-docs/example.md index bcb599d037..04d20dee17 100644 --- a/scribble-test/tests/scribble/markdown-docs/example.md +++ b/scribble-test/tests/scribble/markdown-docs/example.md @@ -14,10 +14,27 @@ This is a subsubsection. Here is an itemize: -* Item 1. +* This sentence is really long and should really be broken up into + multiple lines because wow it is so long. * Item 2. +Here is an ordered itemize, starting at 10. + +10) This sentence is really long and should really be broken up into + multiple lines because wow it is so long. + +11) Item 11. + + +Here is an ordered itemize, with the normal start. + +1) This sentence is really long and should really be broken up into + multiple lines because wow it is so long. + +2) Item 2. + + Here is a hyperlink: [I am a hyperlink to Racket.](http://racket-lang.org/) diff --git a/scribble-test/tests/scribble/markdown-docs/example.scrbl b/scribble-test/tests/scribble/markdown-docs/example.scrbl index 4f938b5278..e7bf7bb601 100644 --- a/scribble-test/tests/scribble/markdown-docs/example.scrbl +++ b/scribble-test/tests/scribble/markdown-docs/example.scrbl @@ -22,7 +22,24 @@ This is a subsubsection. Here is an itemize: @itemize[ -@item{Item 1.} +@item{This sentence is really long and should really be broken up into multiple lines + because wow it is so long.} +@item{Item 2.} +] + +Here is an ordered itemize, starting at 10. + +@itemize[#:style (ordered #:start 10) +@item{This sentence is really long and should really be broken up into multiple lines + because wow it is so long.} +@item{Item 11.} +] + +Here is an ordered itemize, with the normal start. + +@itemize[#:style (ordered) +@item{This sentence is really long and should really be broken up into multiple lines + because wow it is so long.} @item{Item 2.} ]