Improve the scribble/acmart language

The existing scribble/acmart language in this repo felt more like latex than Scribble. This package brings scribble/acmart more inline with the existing `scribble/acmart` package that was already on the package server. In particular, this commit:

* Remove maketitle from scribble/acmart

* Extends the title form to also have the fields in `scribble/base`'s title.

* Support author information. (Like scribble/sigplans authorinfo)

* Removed unneeded functions now redundant due to the author function. Namely, affiliation based ones.

* Factor out common functions to scribble/acmart and scribble/base into private module.

These functions might make sense to be public, but since they were already private in base
I thought it made sense to leave them that way. Additionally, it might make sense to have the
file be something other than private/tag, as private/tag currently requires tag, which is
different than the normal way where its tag that requires private/tag.

* Add short-title to scribble/latex-properties

* Adds an `command-optional` property which is like `command-extras`, but is a single
optional argument placed before the mandatory ones.

* Create email, affiliation, and institution structs so that authors can have multiple of each.

* Add/improve documentation and history (and bump version number).
This commit is contained in:
Leif Andersen 2017-03-21 01:06:02 -04:00 committed by GitHub
parent 82860694a2
commit 558a8a5c64
12 changed files with 389 additions and 110 deletions

View File

@ -62,19 +62,6 @@ number of options may be used:
If multiple font size options are used, all but the last are ignored. If multiple font size options are used, all but the last are ignored.
} }
@defproc[(maketitle) block?]{
Issues the @tt{maketitle} command. This @emph{must} be included in
the document and should occur after the title, authors, and several
other top-matter commands. (See the
@hyperlink[acmart-url]{@tt{acmart}} documentation.)
@codeblock|{
#lang scribble/acmart
@title{Example}
@maketitle{}
}|}
@defproc[(abstract [pre-content pre-content?] ...) block?]{ @defproc[(abstract [pre-content pre-content?] ...) block?]{
Generates a @tech{nested flow} for a paper abstract.} Generates a @tech{nested flow} for a paper abstract.}
@ -85,7 +72,14 @@ Similar to @racket[include-section], but incorporates the document in the
specified module as an abstract. The document must have no title or specified module as an abstract. The document must have no title or
sub-parts.} sub-parts.}
@defproc[(title [#:short short-title pre-content? #f] [title pre-content?]) content?]{ @defproc[(title [#:short short-title pre-content? #f]
[#:tag tag (or/c string? (listof string?) #f) #f]
[#:tag-prefix prefix (or/c string? module-path? #f) #f]
[#:style style (or/c style? string? symbol? #f) #f]
[#:version version (or/c string? #f) #f]
[#:date date (or/c string? #f) #f]
[title pre-content?] ...)
title-decl?]{
Specifies the title of the document, optionally with a short version of the title for running heads.} Specifies the title of the document, optionally with a short version of the title for running heads.}
@ -93,13 +87,23 @@ Specifies the title of the document, optionally with a short version of the titl
Specifies a subtitle.} Specifies a subtitle.}
@defproc[(author [pre-content pre-conent?] ...) content?]{ @defproc[(author [#:orcid orcid (or/c pre-content? #f) #f]
[#:affiliation affiliation
(or/c pre-content?
affiliation?
(listof pre-content?)
(listof affiliation?)
#f)
#f]
[#:email email
(or/c pre-content? (listof pre-content?) #f)
#f]
[name pre-content?] ...)
block?]{
Specifies an author.} Specifies an author with an optional email address, affiliation, and/or orcid.
@defproc[(email [pre-content pre-conent?] ...) content?]{ }
Specifies an author's email address.}
@deftogether[( @deftogether[(
@defproc[(acmJournal [journal pre-content?] ...) content?] @defproc[(acmJournal [journal pre-content?] ...) content?]
@ -128,40 +132,66 @@ screen version of the image links to the badge authority.
} }
@defproc[(affiliation [content pre-content?] ...) content?]{ @defproc[(email [text pre-content?] ...)
email?]{
Creates an @racket[email?] object for use with @racket[author].
}
Declares information about the affiliation of an author.} @defproc[(email? [email any/c]) boolean?]{
@deftogether[( Returns @racket[#t] if @racket[email] is an @racket[email],
@defproc[(position [content pre-content?] ...) content?] @racket[#f] otherwise.
@defproc[(institution [content pre-content?] ...) content?] }
@defproc[(department [content pre-content?] ...) content?]
@defproc[(streetaddress [content pre-content?] ...) content?]
@defproc[(city [content pre-content?] ...) content?]
@defproc[(state [content pre-content?] ...) content?]
@defproc[(postcode [content pre-content?] ...) content?]
@defproc[(country [content pre-content?] ...) content?]
)]{
Declares information that is collected for each author. These commands should
only be used within an @racket[affiliation] command.} @defproc[(affiliation
[#:position position (or/c pre-content? #f) #f]
[#:institution institution (or/c pre-content? institution? #f) #f]
[#:street-address street-address (or/c pre-content? #f) #f]
[#:city city (or/c pre-content? #f) #f]
[#:state state (or/c pre-content? #f) #f]
[#:postcode postcode (or/c pre-content? #f) #f]
[#:country country (or/c pre-content? #f) #f])
affiliation?]{
Creates an @racket[affiliation?] object for use with @racket[author].
}
@defproc[(affiliation? [aff any/c]) boolean?]{
Returns @racket[#t] if @racket[aff] is an
@racket[affiliation], @racket[#f] otherwise.
}
@defproc[(institution [#:departments departments (or/c pre-content? institution? (listof institution)) '()]
[inst institution?] ...)
institution?]{
Creates an @racket[institution?] object for use in @racket[author].}
@defproc[(institution? [inst any/c]) boolean]{
Returns @racket[#t] if @racket[inst] is an
@racket[institution], @racket[#f] otherwise.
}
@codeblock|{ @codeblock|{
#lang scribble/acmart #lang scribble/acmart
@title{Some Title} @title{Some Title}
@author{David Van Horn} @author["David Van Horn"
@email|{dvanhorn@cs.umd.edu}| #:affiliation @affiliation[
@affiliation{ #:institution
@department{Department of Computer Science and UMIACS} @institution[
@institution{University of Maryland} #:departments (list @institution{Department of Computer Science}
@city{College Park} @institution{UMIACS})]{
@state{Maryland}} University of Maryland}
#:city "College Park"
#:state "Maryland"]
#:email "dvanhorn@cs.umd.edu"]}
@abstract{This is an abstract.} @abstract{This is an abstract.}
@maketitle{}
}| }|
@deftogether[( @deftogether[(
@defproc[(terms [content pre-content?] ...) content?] @defproc[(terms [content pre-content?] ...) content?]
@defproc[(keywords [content pre-content?] ...) content?] @defproc[(keywords [content pre-content?] ...) content?]
@ -198,14 +228,6 @@ defaults to @racket{Received} for the first occurrence and
@received[#:stage "accepted"]{June 2009} @received[#:stage "accepted"]{June 2009}
}|} }|}
@defproc[(citestyle [content pre-content?]) content?]{
Sets the citation style for the paper.}
@defproc[(setcitestyle [content pre-content?] ...) content?]{
Sets customization options for the citation style for the paper.}
@defproc[(teaserfigure [content pre-content?] ...) block?]{ @defproc[(teaserfigure [content pre-content?] ...) block?]{
Creates a teaser figure to appear before main text.} Creates a teaser figure to appear before main text.}
@ -254,3 +276,5 @@ sponsors, @racket[name] is the name of the sponsor. The
"National Scribble Foundation"]{http://racket-lang.org} under "National Scribble Foundation"]{http://racket-lang.org} under
grant No.: @grantnum["NSF7000"]{867-5309}.} grant No.: @grantnum["NSF7000"]{867-5309}.}
}|} }|}
@history[#:added "1.20"]

View File

@ -118,7 +118,7 @@ A @deftech{block} is either a @techlink{table}, an
@itemize[ @itemize[
@item{An @deftech{content} can be a string, one of a few @item{A @deftech{content} can be a string, one of a few
symbols, an instance of @racket[element] (possibly symbols, an instance of @racket[element] (possibly
@racket[link-element], etc.), a @racket[multiarg-element], a @racket[link-element], etc.), a @racket[multiarg-element], a
@techlink{traverse element}, a @techlink{part-relative element}, a @techlink{traverse element}, a @techlink{part-relative element}, a
@ -1799,3 +1799,20 @@ See also @racketmodname[scribble/latex-prefix].}
Used as a @tech{style property} on an @racket[element] to add extra Used as a @tech{style property} on an @racket[element] to add extra
arguments to the element's command in Latex output.} arguments to the element's command in Latex output.}
@defstruct[command-optional ([argument string?])]{
Used as a @tech{style property} on a @racket[element] to add
an optional argument to the element's command in Latex output.
@history[#:added "1.20"]
}
@defstruct[short-title ([text (or/c string? #f)])]{
Used as a @tech{style property} on a @racket[title-decl].
Attaches a short title to the title for a @racket[part] if
the Latex class file uses a short title.
@history[#:added "1.20"]
}

View File

@ -23,4 +23,4 @@
(define pkg-authors '(mflatt eli)) (define pkg-authors '(mflatt eli))
(define version "1.19") (define version "1.20")

View File

@ -1,15 +1,69 @@
#lang racket/base #lang racket/base
(require setup/collects (require setup/collects
racket/contract/base racket/contract/base
racket/list
scribble/core scribble/core
scribble/base scribble/base
scribble/decode scribble/decode
scribble/html-properties scribble/html-properties
scribble/latex-properties scribble/latex-properties
scribble/private/tag
(for-syntax racket/base)) (for-syntax racket/base))
(struct affiliation (position institution street-address city state postcode country)
#:constructor-name author-affiliation
#:name author-affiliation
#:transparent)
(struct email (text)
#:constructor-name author-email
#:name author-email
#:transparent)
(struct institution (name departments)
#:constructor-name author-institution
#:name author-institution
#:transparent)
(provide/contract (provide/contract
[title (->* (pre-content?) (#:short pre-content?) content?)] [title (->* ()
(#:short pre-content?
#:tag (or/c string? (listof string?) #f)
#:tag-prefix (or/c string? module-path? #f)
#:style (or/c style? string? symbol? #f)
#:version (or/c string? #f)
#:date (or/c string? #f))
#:rest (listof pre-content?)
title-decl?)]
[author (->* ()
(#:orcid (or/c pre-content? #f)
#:affiliation (or/c pre-content?
affiliation?
(listof affiliation?)
#f)
#:email (or/c pre-content? email? (listof email?) #f))
#:rest (listof pre-content?)
block?)]
[institution (->* ()
(#:departments (listof (or/c pre-content? institution?)))
#:rest pre-content?
institution?)]
[institution? (-> any/c boolean?)]
[email (->* ()
#:rest (listof pre-content?)
email?)]
[email? (-> any/c boolean?)]
[affiliation (->* ()
(#:position (or/c pre-content? #f)
#:institution (or/c pre-content? institution? (listof institution?) #f)
#:street-address (or/c pre-content? #f)
#:city (or/c pre-content? #f)
#:state (or/c pre-content? #f)
#:postcode (or/c pre-content? #f)
#:country (or/c pre-content? #f))
affiliation?)]
[affiliation? (-> any/c boolean?)]
[abstract [abstract
(->* () () #:rest (listof pre-content?) (->* () () #:rest (listof pre-content?)
block?)] block?)]
@ -30,8 +84,6 @@
(->* () () #:rest (listof pre-content?) (->* () () #:rest (listof pre-content?)
any/c)]) any/c)])
(provide maketitle)
(define-syntax-rule (defopts name ...) (define-syntax-rule (defopts name ...)
(begin (define-syntax (name stx) (begin (define-syntax (name stx)
(raise-syntax-error #f (raise-syntax-error #f
@ -99,9 +151,6 @@
abstract-style abstract-style
(decode-flow strs))) (decode-flow strs)))
(define (maketitle)
(make-nested-flow (make-style "maketitle" command-props) '()))
(define (extract-abstract p) (define (extract-abstract p)
(unless (part? p) (unless (part? p)
(error 'include-abstract "doc binding is not a part: ~e" p)) (error 'include-abstract "doc binding is not a part: ~e" p))
@ -179,24 +228,159 @@
(make-element (make-style "ccsdesc" command-props) (make-element (make-style "ccsdesc" command-props)
(decode-string str)))) (decode-string str))))
(define (title #:short [st #f] str) (define (title #:tag [tag #f]
(if st #:tag-prefix [prefix #f]
(make-multiarg-element (make-style "StitleShort" multicommand-props) #:style [style plain]
(list (decode-string st) #:version [version #f]
(decode-string str))) #:date [date #f]
(make-element (make-style "title" command-props) #:short [short #f]
(decode-string str)))) . str)
(let ([content (decode-content str)])
(make-title-decl (prefix->string prefix)
(convert-tag tag content)
version
(let* ([s (convert-part-style 'title style)]
[s (if date
(make-style (style-name s)
(cons (make-document-date date)
(style-properties s)))
s)]
[s (if short
(make-style (style-name s)
(cons (short-title short)
(style-properties s)))
s)])
s)
content)))
(define (author #:orcid [orcid #f]
#:affiliation [affiliation '()]
#:email [email '()]
. name)
(make-paragraph
(make-style 'author command-props)
(decode-content
(list
(make-multiarg-element (make-style "SAuthorinfo" multicommand-props)
(list (make-element #f (decode-content name))
(make-element #f
(if orcid
(make-element
(make-style "SAuthorOrcid" multicommand-props)
(decode-content (list orcid)))
'()))
(make-element #f
(cond
[(affiliation? affiliation)
(convert-affiliation affiliation)]
[(pre-content? affiliation)
(make-element
(make-style "SAuthorPlace" multicommand-props)
(decode-content (list affiliation)))]
[else
(for/list ([a (in-list affiliation)])
(convert-affiliation a))]))
(make-element #f
(cond
[(email? email)
(convert-email email)]
[(pre-content? email)
(make-element
(make-style "SAuthorEmail" multicommand-props)
(decode-content (list email)))]
[else
(for/list ([e (in-list email)])
(convert-email e))]))))))))
(define-commands subtitle orcid author affiliation email (define (institution #:departments [departments '()]
position institution department streetaddress city state postcode country . name)
(author-institution name departments))
(define (convert-institution inst
#:department? [department? #f])
(define level 0)
(define (mk-inst name
#:department? [department? department?]
#:level [level level])
(displayln department?)
(case department?
[(#f) (make-element (make-style "institution" command-props)
(decode-content name))]
[(sub) (make-element (make-style "department"
(cons (command-optional (number->string level))
command-props))
(decode-content name))]
[else (make-element (make-style "department"
(append
(if (> level 0)
(list (command-optional (number->string level)))
(list))
command-props))
(decode-content name))]))
(define lst
(append
(for/list ([i (in-list (institution-departments inst))])
(cond
[(institution? i)
(define-values (content new-level)
(convert-institution i
#:department? (or (and department? 'sub)
#t)))
(set! level (max level (+ 1 new-level)))
content]
[else
(set! level 1)
(mk-inst (list i)
#:department? (or (and department? 'sub)
#t)
#:level 0)]))
(list (mk-inst (institution-name inst)))))
(if department?
(values lst level)
lst))
(define (email . text)
(author-email text))
(define (convert-email email)
(make-element
(make-style "SAuthorEmail" command-props)
(decode-content (email-text email))))
(define (affiliation #:position [position #f]
#:institution [institution #f]
#:street-address [street-address #f]
#:city [city #f]
#:state [state #f]
#:postcode [postcode #f]
#:country [country #f])
(author-affiliation position institution street-address city state postcode country))
(define (convert-affiliation aff)
(define (maybe-element str content)
(and (content aff) (make-element str (decode-content (list (content aff))))))
(make-element
(make-style "SAuthorPlace" command-props)
(make-multiarg-element
(make-style #f multicommand-props)
(filter values
(append (list (maybe-element "position" affiliation-position))
(if (institution? (affiliation-institution aff))
(convert-institution (affiliation-institution aff))
(list (maybe-element "institution" affiliation-institution)))
(list (maybe-element "streetaddress" affiliation-street-address)
(maybe-element "city" affiliation-city)
(maybe-element "state" affiliation-state)
(maybe-element "postcode" affiliation-postcode)
(maybe-element "country" affiliation-country)))))))
(define-commands subtitle
thanks titlenote subtitlenote authornote acmVolume acmNumber acmArticle acmYear acmMonth thanks titlenote subtitlenote authornote acmVolume acmNumber acmArticle acmYear acmMonth
acmArticleSeq acmPrice acmISBN acmDOI acmArticleSeq acmPrice acmISBN acmDOI
startPage terms keywords startPage terms keywords
setcopyright copyrightyear setcopyright copyrightyear
settopmatter ; could be "Rackety" settopmatter ; could be "Rackety"
shortauthors shortauthors)
setcitstyle)
(define (CCSXML . strs) (define (CCSXML . strs)
(make-nested-flow (make-style "CCSXML" '()) (make-nested-flow (make-style "CCSXML" '())

View File

@ -4,8 +4,10 @@
% These are replaced by scribble/acmart/style.tex, % These are replaced by scribble/acmart/style.tex,
% which is used in combination with acmart.cls % which is used in combination with acmart.cls
\newcommand{\SAuthorinfo}[4]{#1}
\newcommand{\SAuthorPlace}[1]{#1} \newcommand{\SAuthorPlace}[1]{#1}
\newcommand{\SAuthorEmail}[1]{#1} \newcommand{\SAuthorEmail}[1]{#1}
\newcommand{\SAuthorOrcid}[1]{#1}
\newcommand{\SConferenceInfo}[2]{} \newcommand{\SConferenceInfo}[2]{}
\newcommand{\SCopyrightYear}[1]{} \newcommand{\SCopyrightYear}[1]{}

View File

@ -145,5 +145,5 @@
;; Ensure that "acmart.tex" is used, since "style.tex" ;; Ensure that "acmart.tex" is used, since "style.tex"
;; re-defines commands. ;; re-defines commands.
(struct-copy part doc [to-collect (struct-copy part doc [to-collect
(cons '(terms) ; FIXME (cons (terms) ; FIXME
(part-to-collect doc))])) (part-to-collect doc))]))

View File

@ -1,6 +1,6 @@
% Define \SXtitle to lift \SSubtitle out: % Define \SXtitle to lift \SSubtitle out:
\def\SXtitle#1{\title{\let\SSubtitle\SSubtitleDrop#1}\SExtractSubtitle#1\SExtractSubtitleDone} \newcommand{\SXtitle}[2][]{\title#1{\let\SSubtitle\SSubtitleDrop#2}\SExtractSubtitle#2\SExtractSubtitleDone}
\def\SSubtitleDrop#1{} \def\SSubtitleDrop#1{}
\def\SExtractSubtitleDone {} \def\SExtractSubtitleDone {}
\def\SExtractSubtitle{\futurelet\next\SExtractSubtitleX} \def\SExtractSubtitle{\futurelet\next\SExtractSubtitleX}
@ -8,16 +8,30 @@
\def\SExtractSubtitleY{\ifx\next\SExtractSubtitleDone \let\Snext\relax \else \let\Snext\SExtractSubtitle \fi \Snext} \def\SExtractSubtitleY{\ifx\next\SExtractSubtitleDone \let\Snext\relax \else \let\Snext\SExtractSubtitle \fi \Snext}
\def\SWithSubtitle#1{\subtitle{#1}\SExtractSubtitle} \def\SWithSubtitle#1{\subtitle{#1}\SExtractSubtitle}
\renewcommand{\titleAndVersionAndAuthors}[3]{\SXtitle{#1}#3} \renewcommand{\titleAndVersionAndAuthors}[3]{\SXtitle{#1}#3\maketitle}
\renewcommand{\titleAndEmptyVersionAndAuthors}[3]{\titleAndVersionAndAuthors{#1}{#2}{#3}} \renewcommand{\titleAndEmptyVersionAndAuthors}[3]{\titleAndVersionAndAuthors{#1}{#2}{#3}}
\renewcommand{\titleAndVersionAndEmptyAuthors}[3]{\SXtitle{#1}\author{Anonymous Author(s)}} \renewcommand{\titleAndVersionAndEmptyAuthors}[3]{\SXtitle{#1}\author{Anonymous Author(s)}\maketitle}
\renewcommand{\titleAndEmptyVersionAndEmptyAuthors}[3]{\titleAndVersionAndEmptyAuthors{#1}{#2}{#3}} \renewcommand{\titleAndEmptyVersionAndEmptyAuthors}[3]{\titleAndVersionAndEmptyAuthors{#1}{#2}{#3}}
\renewcommand{\titleAndVersionAndAuthorsAndShort}[4]{\SXtitle[[#4]]{#1}#3\maketitle}
\renewcommand{\titleAndEmptyVersionAndAuthorsAndShort}[4]{\titleAndVersionAndAuthorsAndShort{#1}{#2}{#3}{#4}}
\renewcommand{\titleAndVersionAndEmptyAuthorsAndShort}[4]{\SXtitle[[#4]]{#1}\author{Anonymous Author(s)}\maketitle}
\renewcommand{\titleAndEmptyVersionAndEmptyAuthorsAndShort}[4]{\titleAndVersionAndEmptyAuthorsAndShort{#1}{#2}{#3}{#4}}
% Support plain `author' while enabling `authorinfo': for each % Support plain `author' while enabling `authorinfo': for each
% use of \SAuthor, check whether it contains an \SAuthorinfo form: % use of \SAuthor, check whether it contains an \SAuthorinfo form:
\def\SAuthor#1{\author{#1}} \def\SAuthor#1{\SAutoAuthor#1\SAutoAuthorDone{#1}}
\def\SAutoAuthorDone#1{}
\def\SAutoAuthor{\futurelet\next\SAutoAuthorX}
\def\SAutoAuthorX{\ifx\next\SAuthorinfo \let\Snext\relax \else \let\Snext\SToAuthorDone \fi \Snext}
\def\SToAuthorDone{\futurelet\next\SToAuthorDoneX}
\def\SToAuthorDoneX#1{\ifx\next\SAutoAuthorDone \let\Snext\SAddAuthorInfo \else \let\Snext\SToAuthorDone \fi \Snext}
\newcommand{\SAddAuthorInfo}[1]{\SAuthorinfo{#1}{}{}}
\renewcommand{\SAuthorinfo}[4]{\author{#1}{#2}{#3}{#4}}
\renewcommand{\SAuthorSep}[1]{} \renewcommand{\SAuthorSep}[1]{}
\renewcommand{\SAuthorOrcid}[1]{\orcid{#1}}
\renewcommand{\SAuthorPlace}[1]{\affiliation{#1}}
\renewcommand{\SAuthorEmail}[1]{\email{#1}}
\renewcommand{\SConferenceInfo}[2]{\conferenceinfo{#1}{#2}} \renewcommand{\SConferenceInfo}[2]{\conferenceinfo{#1}{#2}}
\renewcommand{\SCopyrightYear}[1]{\copyrightyear{#1}} \renewcommand{\SCopyrightYear}[1]{\copyrightyear{#1}}

View File

@ -6,6 +6,7 @@
"decode-struct.rkt" "decode-struct.rkt"
"html-properties.rkt" "html-properties.rkt"
"tag.rkt" "tag.rkt"
"private/tag.rkt"
scheme/list scheme/list
scheme/class scheme/class
racket/contract/base racket/contract/base
@ -42,34 +43,6 @@
block?)]) block?)])
(provide include-section) (provide include-section)
(define (gen-tag content)
(datum-intern-literal
;; Generate tag from ASCII plus CJK characters. Constraining to
;; ASCII for most purposes helps avoid encoding issues for
;; uncooperative environments, but constraining to ASCII is too
;; uncooperative in another direction for CJK text (i.e., creates
;; too many conflicting tags).
(regexp-replace* #px"[^-a-zA-Z0-9_=\u4e00-\u9fff\u3040-\u309F\u30A0-\u30FF]" (content->string content) "_")))
(define (prefix->string p)
(and p (if (string? p)
(datum-intern-literal p)
(module-path-prefix->string p))))
(define (convert-tag tag content)
(if (list? tag)
(append-map (lambda (t) (convert-tag t content)) tag)
`((part ,(or tag (gen-tag content))))))
(define (convert-part-style who s)
(cond
[(style? s) s]
[(not s) plain]
[(string? s) (make-style s null)]
[(symbol? s) (make-style #f (list s))]
[(and (list? s) (andmap symbol? s)) (make-style #f s)]
[else (raise-argument-error who "(or/c style? string? symbol? (listof symbol?) #f)" s)]))
(define (title #:tag [tag #f] #:tag-prefix [prefix #f] #:style [style plain] (define (title #:tag [tag #f] #:tag-prefix [prefix #f] #:style [style plain]
#:version [version #f] #:date [date #f] #:version [version #f] #:date [date #f]
. str) . str)

View File

@ -10,4 +10,6 @@
[extra-files (listof (or/c path-string? (cons/c 'collects (listof bytes?))))])] [extra-files (listof (or/c path-string? (cons/c 'collects (listof bytes?))))])]
[(latex-defaults+replacements latex-defaults) [(latex-defaults+replacements latex-defaults)
([replacements (hash/c string? (or/c bytes? path-string? (cons/c 'collects (listof bytes?))))])] ([replacements (hash/c string? (or/c bytes? path-string? (cons/c 'collects (listof bytes?))))])]
[command-extras ([arguments (listof string?)])]) [command-extras ([arguments (listof string?)])]
[command-optional ([argument string?])]
[short-title ([text (or/c string? #f)])])

View File

@ -83,6 +83,12 @@
extract-authors extract-authors
extract-pretitle) extract-pretitle)
(define/public (extract-short-title d)
(ormap (lambda (v)
(and (short-title? v)
(short-title-text v)))
(style-properties (part-style d))))
(define/override (auto-extra-files? v) (latex-defaults? v)) (define/override (auto-extra-files? v) (latex-defaults? v))
(define/override (auto-extra-files-paths v) (latex-defaults-extra-files v)) (define/override (auto-extra-files-paths v) (latex-defaults-extra-files v))
@ -145,14 +151,16 @@
(let ([vers (extract-version d)] (let ([vers (extract-version d)]
[date (extract-date d)] [date (extract-date d)]
[pres (extract-pretitle d)] [pres (extract-pretitle d)]
[auths (extract-authors d)]) [auths (extract-authors d)]
[short (extract-short-title d)])
(for ([pre (in-list pres)]) (for ([pre (in-list pres)])
(printf "\n\n") (printf "\n\n")
(do-render-paragraph pre d ri #t #f)) (do-render-paragraph pre d ri #t #f))
(when date (printf "\\date{~a}\n" date)) (when date (printf "\\date{~a}\n" date))
(printf "\\titleAnd~aVersionAnd~aAuthors{" (printf "\\titleAnd~aVersionAnd~aAuthors~a{"
(if (equal? vers "") "Empty" "") (if (equal? vers "") "Empty" "")
(if (null? auths) "Empty" "")) (if (null? auths) "Empty" "")
(if short "AndShort" ""))
(render-content (part-title-content d) d ri) (render-content (part-title-content d) d ri)
(printf "}{~a}{" vers) (printf "}{~a}{" vers)
(unless (null? auths) (unless (null? auths)
@ -161,7 +169,9 @@
(unless first? (printf "\\SAuthorSep{}")) (unless first? (printf "\\SAuthorSep{}"))
(do-render-paragraph auth d ri #t #f) (do-render-paragraph auth d ri #t #f)
#f) #f)
(printf "}\n")))) (if short
(printf "}{~a}\n" short)
(printf "}\n")))))
(render-part d ri) (render-part d ri)
(when whole-doc? (when whole-doc?
(printf "\n\n\\postDoc\n\\end{document}\n")))) (printf "\n\n\\postDoc\n\\end{document}\n"))))
@ -476,6 +486,9 @@
[(multiarg-element? e) [(multiarg-element? e)
(check-render) (check-render)
(printf "\\~a" style-name) (printf "\\~a" style-name)
(define maybe-optional
(findf command-optional? (if style (style-properties style) '())))
(and maybe-optional (printf "[~a]" maybe-optional))
(if (null? (multiarg-element-contents e)) (if (null? (multiarg-element-contents e))
(printf "{}") (printf "{}")
(for ([i (in-list (multiarg-element-contents e))]) (for ([i (in-list (multiarg-element-contents e))])
@ -484,7 +497,13 @@
(render-content i part ri)) (render-content i part ri))
(printf "}")))] (printf "}")))]
[else [else
(wrap e style-name tt?)]))] (define maybe-optional
(findf command-optional? (if style (style-properties style) '())))
(wrap e
(if maybe-optional
(format "~a[~a]" style-name (command-optional-argument maybe-optional))
style-name)
tt?)]))]
[(and (not style-name) [(and (not style-name)
style style
(memq 'exact-chars (style-properties style))) (memq 'exact-chars (style-properties style)))

View File

@ -0,0 +1,40 @@
#lang scheme/base
;; It might make sense to make these functions public, but since they weren't originally,
;; I am going to keep them in the private folder for now.
;; -- With Love, Leif
(provide (all-defined-out))
(require racket/list
scribble/core
"../tag.rkt")
(define (gen-tag content)
(datum-intern-literal
;; Generate tag from ASCII plus CJK characters. Constraining to
;; ASCII for most purposes helps avoid encoding issues for
;; uncooperative environments, but constraining to ASCII is too
;; uncooperative in another direction for CJK text (i.e., creates
;; too many conflicting tags).
(regexp-replace* #px"[^-a-zA-Z0-9_=\u4e00-\u9fff\u3040-\u309F\u30A0-\u30FF]"
(content->string content) "_")))
(define (convert-tag tag content)
(if (list? tag)
(append-map (lambda (t) (convert-tag t content)) tag)
`((part ,(or tag (gen-tag content))))))
(define (convert-part-style who s)
(cond
[(style? s) s]
[(not s) plain]
[(string? s) (make-style s null)]
[(symbol? s) (make-style #f (list s))]
[(and (list? s) (andmap symbol? s)) (make-style #f s)]
[else (raise-argument-error who "(or/c style? string? symbol? (listof symbol?) #f)" s)]))
(define (prefix->string p)
(and p (if (string? p)
(datum-intern-literal p)
(module-path-prefix->string p))))

View File

@ -301,6 +301,10 @@
\newcommand{\titleAndVersionAndEmptyAuthors}[3]{\title{#1\\{\normalsize \SVersionBefore{}#2}}#3\maketitle} \newcommand{\titleAndVersionAndEmptyAuthors}[3]{\title{#1\\{\normalsize \SVersionBefore{}#2}}#3\maketitle}
\newcommand{\titleAndEmptyVersionAndAuthors}[3]{\title{#1}\author{#3}\maketitle} \newcommand{\titleAndEmptyVersionAndAuthors}[3]{\title{#1}\author{#3}\maketitle}
\newcommand{\titleAndEmptyVersionAndEmptyAuthors}[3]{\title{#1}\maketitle} \newcommand{\titleAndEmptyVersionAndEmptyAuthors}[3]{\title{#1}\maketitle}
\newcommand{\titleAndVersionAndAuthorsAndShort}[4]{\title[#4]{#1\\{\normalsize \SVersionBefore{}#2}}\author{#3}\maketitle}
\newcommand{\titleAndVersionAndEmptyAuthorsAndShort}[4]{\title[#4]{#1\\{\normalsize \SVersionBefore{}#2}}#3\maketitle}
\newcommand{\titleAndEmptyVersionAndAuthorsAndShort}[4]{\title[#4]{#1}\author{#3}\maketitle}
\newcommand{\titleAndEmptyVersionAndEmptyAuthorsAndShort}[4]{\title[#4]{#1}\maketitle}
\newcommand{\SAuthor}[1]{#1} \newcommand{\SAuthor}[1]{#1}
\newcommand{\SAuthorSep}[1]{\qquad} \newcommand{\SAuthorSep}[1]{\qquad}
\newcommand{\SVersionBefore}[1]{Version } \newcommand{\SVersionBefore}[1]{Version }