Merge tag 'v6.10' into my-changes-rebased

This commit is contained in:
Suzanne Soy 2021-07-06 02:28:59 +01:00
commit 8f15b78615
16 changed files with 641 additions and 235 deletions

View File

@ -13,6 +13,17 @@ LaTeX style defaults to use the @hyperlink[acmart-url]{@tt{acmart}}
class for typesetting publications for the Association of Computing class for typesetting publications for the Association of Computing
Machinery.} Machinery.}
@bold{Note:} a @racketmodname[scribble/acmart] document must include a
@racket[title] and @racket[author].
Example:
@verbatim[#:indent 2]|{
#lang scribble/acmart
@title{Surreal Numbers}
@author{Ursula N. Owens}
}|
@deftogether[( @deftogether[(
@defidform[manuscript] @defidform[manuscript]
@defidform[acmsmall] @defidform[acmsmall]
@ -146,7 +157,7 @@ screen version of the image links to the badge authority.
@defproc[(affiliation @defproc[(affiliation
[#:position position (or/c pre-content? #f) #f] [#:position position (or/c pre-content? #f) #f]
[#:institution institution (or/c pre-content? institution? #f) #f] [#:institution institution (listof (or/c pre-content? institution?)) '()]
[#:street-address street-address (or/c pre-content? #f) #f] [#:street-address street-address (or/c pre-content? #f) #f]
[#:city city (or/c pre-content? #f) #f] [#:city city (or/c pre-content? #f) #f]
[#:state state (or/c pre-content? #f) #f] [#:state state (or/c pre-content? #f) #f]
@ -277,4 +288,4 @@ sponsors, @racket[name] is the name of the sponsor. The
grant No.: @grantnum["NSF7000"]{867-5309}.} grant No.: @grantnum["NSF7000"]{867-5309}.}
}|} }|}
@history[#:added "1.20"] @history[#:added "1.20"]

View File

@ -260,6 +260,7 @@ used for a new cell. A @racket['cont] must not appear as the first
cell in a row. cell in a row.
The @racket[style] argument is handled the same as @racket[para]. The @racket[style] argument is handled the same as @racket[para].
See @racket[table] for a list of recognized @tech{style names} and @tech{style properties}.
If @racket[sep] is not @racket[#f], it is inserted as a new column If @racket[sep] is not @racket[#f], it is inserted as a new column
between every column in the table; note that any between every column in the table; note that any

View File

@ -282,13 +282,13 @@ an evaluator (e.g., because it is defined in a module body).}
@defparam[scribble-eval-handler handler @defparam[scribble-eval-handler handler
((any/c . -> . any) any/c boolean? . -> . any)]{ ((any/c . -> . any) boolean? any/c . -> . any)]{
A parameter that serves as a hook for evaluation. The evaluator to use A parameter that serves as a hook for evaluation. The evaluator to use
is supplied as the first argument to the parameter's value, and the is supplied as the first argument to the parameter's value.
second argument is the form to evaluate. The last argument is The second argument is @racket[#t] if exceptions are being captured (to display
@racket[#t] if exceptions are being captured (to display exception exception results), @racket[#f] otherwise.
results), @racket[#f] otherwise.} The third argument is the form to evaluate.}
@defparam[scribble-exn->string handler (-> (or/c exn? any/c) string?)]{ @defparam[scribble-exn->string handler (-> (or/c exn? any/c) string?)]{
A parameter that controls how exceptions are rendered by A parameter that controls how exceptions are rendered by

View File

@ -55,16 +55,19 @@ includes a citation to section 8 of the Racket reference.
(code:line #:render-date-in-bib render-date-expr) (code:line #:render-date-in-bib render-date-expr)
(code:line #:render-date-in-cite render-date-expr) (code:line #:render-date-in-cite render-date-expr)
(code:line #:date<? date-compare-expr) (code:line #:date<? date-compare-expr)
(code:line #:date=? date-compare-expr)]) (code:line #:date=? date-compare-expr)
(code:line #:cite-author cite-author-id)
(code:line #:cite-year cite-year-id)])
#:contracts ([style-expr (or/c author+date-style number-style)] #:contracts ([style-expr (or/c author+date-style number-style)]
[spaces-expr number] [spaces-expr number?]
[disambiguator-expr (or/c #f (-> exact-nonnegative-integer? element?))] [disambiguator-expr (or/c #f (-> exact-nonnegative-integer? element?))]
[render-date-expr (or/c #f (-> date? element?))] [render-date-expr (or/c #f (-> date? element?))]
[date-compare-expr (or/c #f (-> date? date? boolean?))])]{ [date-compare-expr (or/c #f (-> date? date? boolean?))])]{
Binds @racket[~cite-id], @racket[citet-id], and Binds @racket[~cite-id], @racket[citet-id],
@racket[generate-bibliography-id], which share state to accumulate and @racket[generate-bibliography-id], (optionally)
render citations. @racket[cite-author-id], and (optionally) @racket[cite-year-id] which
share state to accumulate and render citations.
The function bound to @racket[~cite-id] produces a citation referring The function bound to @racket[~cite-id] produces a citation referring
to one or more bibliography entries with a preceding non-breaking to one or more bibliography entries with a preceding non-breaking
@ -90,6 +93,30 @@ section for the bibliography. It has the contract
(->* () (#:tag string? #:sec-title string?) part?) (->* () (#:tag string? #:sec-title string?) part?)
] ]
If provided, the function bound to @racket[cite-author-id]
generates an element containing the authors of a paper.
@racketblock[
(->* (bib?) element?)
]
If provided, the function bound to @racket[cite-year-id]
generates an element containing the year the paper was
published in, or possibly multiple years if multiple papers
are provided.
@racketblock[
(->* (bib?) #:rest (listof? bib?) element?)
]
The functions bound to @racket[cite-author-id] and
@racket[cite-year-id] make it possible to create possessive textual citations.
@codeblock[#:keep-lang-line? #f]|{
#lang scribble/base
@citeauthor[scribble-cite]'s (@citeyear[scribble-cite]) autobib library is pretty nifty.
}|
The default value for the @racket[#:tag] argument is @racket["doc-bibliography"] The default value for the @racket[#:tag] argument is @racket["doc-bibliography"]
and for @racket[#:sec-title] is @racket["Bibliography"]. and for @racket[#:sec-title] is @racket["Bibliography"].
@ -110,7 +137,10 @@ to add an extra element after the date; the default disambiguator adds
ambiguous raises an exception. Date comparison is controlled by ambiguous raises an exception. Date comparison is controlled by
@racket[date-compare-expr]s. Dates in citations and dates in the @racket[date-compare-expr]s. Dates in citations and dates in the
bibliography may be rendered differently, as specified by the bibliography may be rendered differently, as specified by the
optionally given @racket[render-date-expr] functions.} optionally given @racket[render-date-expr] functions.
@history[#:changed "1.22" "Add optional ids for author-name and author-year"]
}
@deftogether[( @deftogether[(
@defthing[author+date-style any/c] @defthing[author+date-style any/c]
@ -182,9 +212,10 @@ describing a paper's location within a journal.}
element?]{ element?]{
Combines elements to generate an element that is suitable for Combines elements to generate an element that is suitable for
describing a book's location.} describing a book's location.
Both arguments are optional, but at least one must be supplied.}
@defproc[(techrpt-location [#:institution institution edition any/c] @defproc[(techrpt-location [#:institution institution any/c]
[#:number number any/c]) [#:number number any/c])
element?]{ element?]{

View File

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

View File

@ -80,6 +80,8 @@
[CCSXML [CCSXML
(->* () () #:rest (listof pre-content?) (->* () () #:rest (listof pre-content?)
any/c)]) any/c)])
(provide
invisible-element-to-collect-for-acmart-extras)
(define-syntax-rule (defopts name ...) (define-syntax-rule (defopts name ...)
(begin (define-syntax (name stx) (begin (define-syntax (name stx)
@ -136,6 +138,9 @@
(make-css-addition (abs "acmart.css")) (make-css-addition (abs "acmart.css"))
(make-tex-addition (abs "acmart.tex"))))) (make-tex-addition (abs "acmart.tex")))))
(define invisible-element-to-collect-for-acmart-extras
(make-element (make-style "invisible-element-to-collect-for-acmart-extras" acmart-extras) '()))
;; ---------------------------------------- ;; ----------------------------------------
;; Abstracts: ;; Abstracts:
@ -289,7 +294,6 @@
(define (mk-inst name (define (mk-inst name
#:department? [department? department?] #:department? [department? department?]
#:level [level level]) #:level [level level])
(displayln department?)
(case department? (case department?
[(#f) (make-element (make-style "institution" command-props) [(#f) (make-element (make-style "institution" command-props)
(decode-content name))] (decode-content name))]

File diff suppressed because it is too large Load Diff

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 invisible-element-to-collect-for-acmart-extras
(part-to-collect doc))])) (part-to-collect doc))]))

View File

@ -1,20 +1,11 @@
% Define \SXtitle to lift \SSubtitle out: \renewcommand{\titleAndVersionAndAuthors}[3]{\title{#1}#3\maketitle}
\newcommand{\SXtitle}[2][]{\title#1{\let\SSubtitle\SSubtitleDrop#2}\SExtractSubtitle#2\SExtractSubtitleDone}
\def\SSubtitleDrop#1{}
\def\SExtractSubtitleDone {}
\def\SExtractSubtitle{\futurelet\next\SExtractSubtitleX}
\def\SExtractSubtitleX#1{\ifx{#1}\SSubtitle \let\Snext\SWithSubtitle \else \let\Snext\SExtractSubtitleY \fi \Snext}
\def\SExtractSubtitleY{\ifx\next\SExtractSubtitleDone \let\Snext\relax \else \let\Snext\SExtractSubtitle \fi \Snext}
\def\SWithSubtitle#1{\subtitle{#1}\SExtractSubtitle}
\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)}\maketitle} \renewcommand{\titleAndVersionAndEmptyAuthors}[3]{\title{#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{\titleAndVersionAndAuthorsAndShort}[4]{\title[#4]{#1}#3\maketitle}
\renewcommand{\titleAndEmptyVersionAndAuthorsAndShort}[4]{\titleAndVersionAndAuthorsAndShort{#1}{#2}{#3}{#4}} \renewcommand{\titleAndEmptyVersionAndAuthorsAndShort}[4]{\titleAndVersionAndAuthorsAndShort{#1}{#2}{#3}{#4}}
\renewcommand{\titleAndVersionAndEmptyAuthorsAndShort}[4]{\SXtitle[[#4]]{#1}\author{Anonymous Author(s)}\maketitle} \renewcommand{\titleAndVersionAndEmptyAuthorsAndShort}[4]{\title[#4]{#1}\author{Anonymous Author(s)}\maketitle}
\renewcommand{\titleAndEmptyVersionAndEmptyAuthorsAndShort}[4]{\titleAndVersionAndEmptyAuthorsAndShort{#1}{#2}{#3}{#4}} \renewcommand{\titleAndEmptyVersionAndEmptyAuthorsAndShort}[4]{\titleAndVersionAndEmptyAuthorsAndShort{#1}{#2}{#3}{#4}}
% Support plain `author' while enabling `authorinfo': for each % Support plain `author' while enabling `authorinfo': for each

View File

@ -33,18 +33,30 @@
defexamples* defexamples*
as-examples as-examples
make-base-eval (contract-out
make-base-eval-factory [make-base-eval
make-eval-factory (->* [] [#:pretty-print? any/c #:lang lang-option/c] #:rest any/c any)]
close-eval [make-base-eval-factory
eval-factory/c]
[make-eval-factory
eval-factory/c]
[close-eval
(-> any/c any)]
[scribble-exn->string
(-> any/c string?)]
[scribble-eval-handler
(parameter/c (-> (-> any/c any) boolean? any/c any))]
[make-log-based-eval
(-> path-string? (or/c 'record 'replay) any)])
scribble-exn->string
scribble-eval-handler
with-eval-preserve-source-locations) with-eval-preserve-source-locations)
(provide/contract (define lang-option/c
[make-log-based-eval (or/c module-path? (list/c 'special symbol?) (cons/c 'begin list?)))
(-> path-string? (or/c 'record 'replay) (-> any/c any))])
(define eval-factory/c
(->* [(listof module-path?)] [#:pretty-print? any/c #:lang lang-option/c] any))
(define scribble-eval-handler (define scribble-eval-handler
(make-parameter (lambda (ev c? x) (ev x)))) (make-parameter (lambda (ev c? x) (ev x))))

View File

@ -8,12 +8,12 @@
(provide examples (provide examples
;; Re-exports: ;; Re-exports:
make-base-eval make-base-eval
make-base-eval-factory make-base-eval-factory
make-eval-factory make-eval-factory
close-eval close-eval
make-log-based-eval
scribble-exn->string scribble-exn->string
scribble-eval-handler scribble-eval-handler
make-log-based-eval) make-log-based-eval)

View File

@ -1085,6 +1085,9 @@
[(#\↕) "$\\updownarrow$"] [(#\↕) "$\\updownarrow$"]
[(#\↔) "$\\leftrightarrow$"] [(#\↔) "$\\leftrightarrow$"]
[(#\↗) "$\\nearrow$"] [(#\↗) "$\\nearrow$"]
[(#\↝) "$\\leadsto$"]
[(#\↱) "$\\Lsh$"]
[(#\↰) "$\\Rsh$"]
[(#\⇕) "$\\Updownarrow$"] [(#\⇕) "$\\Updownarrow$"]
[(#\א) "$\\aleph$"] [(#\א) "$\\aleph$"]
[(#\) "$\\prime$"] [(#\) "$\\prime$"]
@ -1159,6 +1162,7 @@
[(#\) "$\\vee$"] [(#\) "$\\vee$"]
[(#\∧) "$\\wedge$"] [(#\∧) "$\\wedge$"]
[(#\◃) "$\\triangleright$"] [(#\◃) "$\\triangleright$"]
[(#\◊) "$\\Diamond$"]
[(#\⊙) "$\\odot$"] [(#\⊙) "$\\odot$"]
[(#\★) "$\\star$"] [(#\★) "$\\star$"]
[(#\†) "$\\dagger$"] [(#\†) "$\\dagger$"]

View File

@ -49,8 +49,7 @@
(define vers (history-entry-vers e)) (define vers (history-entry-vers e))
(list (if (zero? i) (list (if (zero? i)
null null
(list null ; needed to avoid " " dropped as whitespace (list (linebreak)))
" "))
(history-entry-what e) (history-entry-what e)
" in version " " in version "
vers vers

View File

@ -16,11 +16,19 @@
(provide define-cite (provide define-cite
author+date-style number-style author+date-style number-style
make-bib in-bib (rename-out [auto-bib? bib?]) make-bib in-bib (rename-out [auto-bib? bib?])
proceedings-location journal-location book-location
techrpt-location dissertation-location
author-name org-author-name author-name org-author-name
(contract-out (contract-out
[authors (->* (content?) #:rest (listof content?) element?)]) [authors (->* (content?) #:rest (listof content?) element?)]
[proceedings-location
(->* [any/c] [#:pages (or/c (list/c any/c any/c) #f) #:series any/c #:volume any/c] element?)]
[journal-location
(->* [any/c] [#:pages (or/c (list/c any/c any/c) #f) #:number any/c #:volume any/c] element?)]
[book-location
(->* [] [#:edition any/c #:publisher any/c] element?)]
[techrpt-location
(-> #:institution any/c #:number any/c element?)]
[dissertation-location
(->* [#:institution any/c] [#:degree any/c] element?)])
other-authors other-authors
editor editor
abbreviate-given-names) abbreviate-given-names)
@ -365,15 +373,17 @@
(define-syntax (define-cite stx) (define-syntax (define-cite stx)
(syntax-parse stx (syntax-parse stx
[(_ (~var ~cite) citet generate-bibliography [(_ (~var ~cite id) citet:id generate-bibliography:id
(~or (~optional (~seq #:style style) #:defaults ([style #'author+date-style])) (~or (~optional (~seq #:style style) #:defaults ([style #'author+date-style]))
(~optional (~seq #:disambiguate fn) #:defaults ([fn #'#f])) (~optional (~seq #:disambiguate fn) #:defaults ([fn #'#f]))
(~optional (~seq #:render-date-in-bib render-date-bib) #:defaults ([render-date-bib #'#f])) (~optional (~seq #:render-date-in-bib render-date-bib) #:defaults ([render-date-bib #'#f]))
(~optional (~seq #:spaces spaces) #:defaults ([spaces #'1])) (~optional (~seq #:spaces spaces) #:defaults ([spaces #'1]))
(~optional (~seq #:render-date-in-cite render-date-cite) #:defaults ([render-date-cite #'#f])) (~optional (~seq #:render-date-in-cite render-date-cite) #:defaults ([render-date-cite #'#f]))
(~optional (~seq #:date<? date<?) #:defaults ([date<? #'#f])) (~optional (~seq #:date<? date<?) #:defaults ([date<? #'#f]))
(~optional (~seq #:date=? date=?) #:defaults ([date=? #'#f]))) ...) (~optional (~seq #:date=? date=?) #:defaults ([date=? #'#f]))
(syntax/loc stx (~optional (~seq #:cite-author cite-author:id) #:defaults ([cite-author #'#f]))
(~optional (~seq #:cite-year cite-year:id) #:defaults ([cite-year #'#f]))) ...)
(quasisyntax/loc stx
(begin (begin
(define group (make-bib-group (make-hasheq))) (define group (make-bib-group (make-hasheq)))
(define the-style style) (define the-style style)
@ -382,7 +392,15 @@
(define (citet bib-entry . bib-entries) (define (citet bib-entry . bib-entries)
(add-inline-cite group (cons bib-entry bib-entries) the-style date<? date=?)) (add-inline-cite group (cons bib-entry bib-entries) the-style date<? date=?))
(define (generate-bibliography #:tag [tag "doc-bibliography"] #:sec-title [sec-title "Bibliography"]) (define (generate-bibliography #:tag [tag "doc-bibliography"] #:sec-title [sec-title "Bibliography"])
(gen-bib tag group sec-title the-style fn render-date-bib render-date-cite date<? date=? spaces))))])) (gen-bib tag group sec-title the-style fn render-date-bib render-date-cite date<? date=? spaces))
#,(when (identifier? #'cite-author)
#'(define (cite-author bib-entry)
(add-cite group bib-entry 'autobib-author #f #f the-style)))
#,(when (identifier? #'cite-year)
#'(define (cite-year bib-entry . bib-entries)
(add-date-cites group (cons bib-entry bib-entries)
(send the-style get-group-sep)
the-style #t date<? date=?)))))]))
(define (ends-in-punc? e) (define (ends-in-punc? e)
(regexp-match? #rx"[.!?,]$" (content->string e))) (regexp-match? #rx"[.!?,]$" (content->string e)))
@ -475,12 +493,12 @@
#:pages [pages #f] #:pages [pages #f]
#:series [series #f] #:series [series #f]
#:volume [volume #f]) #:volume [volume #f])
(let* ([s @elem{In @italic{@elem{Proc. @|location|}}}] (let* ([s @elem{In @italic{@elem{Proc. @to-string[location]}}}]
[s (if series [s (if series
@elem{@|s|, @(format "~a" series)} @elem{@|s|, @to-string[series]}
s)] s)]
[s (if volume [s (if volume
@elem{@|s| volume @(format "~a" volume)} @elem{@|s| volume @to-string[volume]}
s)] s)]
[s (if pages [s (if pages
@elem{@|s|, pp. @(to-string (car pages))--@(to-string (cadr pages))} @elem{@|s|, pp. @(to-string (car pages))--@(to-string (cadr pages))}
@ -492,7 +510,7 @@
#:pages [pages #f] #:pages [pages #f]
#:number [number #f] #:number [number #f]
#:volume [volume #f]) #:volume [volume #f])
(let* ([s @italic{@|location|}] (let* ([s @italic{@to-string[location]}]
[s (if volume [s (if volume
@elem{@|s| @(to-string volume)} @elem{@|s| @(to-string volume)}
s)] s)]
@ -508,12 +526,12 @@
#:edition [edition #f] #:edition [edition #f]
#:publisher [publisher #f]) #:publisher [publisher #f])
(let* ([s (if edition (let* ([s (if edition
@elem{@(string-titlecase edition) edition} @elem{@(string-titlecase (to-string edition)) edition}
#f)] #f)]
[s (if publisher [s (if publisher
(if s (if s
@elem{@|s|. @|publisher|} @elem{@|s|. @to-string[publisher]}
publisher) @elem{@to-string[publisher]})
s)]) s)])
(unless s (unless s
(error 'book-location "no arguments")) (error 'book-location "no arguments"))
@ -522,12 +540,12 @@
(define (techrpt-location (define (techrpt-location
#:institution org #:institution org
#:number num) #:number num)
@elem{@|org|, @|num|}) @elem{@to-string[org], @to-string[num]})
(define (dissertation-location (define (dissertation-location
#:institution org #:institution org
#:degree [degree "PhD"]) #:degree [degree "PhD"])
@elem{@|degree| dissertation, @|org|}) @elem{@to-string[degree] dissertation, @to-string[org]})
;; ---------------------------------------- ;; ----------------------------------------

View File

@ -0,0 +1,45 @@
#lang racket/base
(require rackunit scribble/example setup/path-to-relative
(only-in racket/contract exn:fail:contract:blame?))
(test-case "scribble/example contracts"
(define blames-this-module?
(let* ([this-module
(path->relative-string/library
(variable-reference->module-source (#%variable-reference)))]
[blame-rx (regexp (string-append "blaming: " this-module))])
(λ (x)
(and (exn:fail:contract:blame? x)
(regexp-match? blame-rx (exn-message x))))))
(check-exn blames-this-module?
(λ () (make-base-eval #:lang #f '(+ 2 2))))
(check-exn blames-this-module?
(λ () (make-base-eval #:lang '(+ 2 2))))
(check-exn blames-this-module?
(λ () (make-base-eval-factory 'racket/dict)))
(check-exn blames-this-module?
(λ () (make-base-eval-factory '() #:lang #f '(+ 2 2))))
(check-exn blames-this-module?
(λ () (make-base-eval-factory '() #:lang '(+ 2 2))))
(check-exn blames-this-module?
;; https://github.com/racket/scribble/issues/117
(λ () (make-eval-factory 'racket/dict)))
(check-exn blames-this-module?
(λ () (make-eval-factory '() #:lang #f '(+ 2 2))))
(check-exn blames-this-module?
(λ () (make-eval-factory '() #:lang '(+ 2 2))))
(check-exn blames-this-module?
(λ () (scribble-eval-handler #f)))
(check-exn blames-this-module?
(λ () (scribble-eval-handler (λ (ev t) t))))
(check-exn blames-this-module?
(λ () (make-log-based-eval #f 'record)))
(check-exn blames-this-module?
(λ () (make-log-based-eval "foo.rkt" 'bad-mode)))
)

View File

@ -0,0 +1,56 @@
#lang racket/base
(require rackunit scriblib/autobib)
(test-case "define-cite"
;; Check that `define-cite` binds the expected identifiers
(let ()
(define-cite cite citet gen-bib)
(check-pred values (void cite citet gen-bib)))
(let ()
(define-cite cite citet gen-bib
#:cite-author cite-author
#:cite-year cite-year)
(check-pred values (void cite citet gen-bib cite-author cite-year))))
(test-case "proceedings-location"
(check-not-exn
(λ () (proceedings-location "RacketCon" #:pages '(1 2) #:series 3 #:volume 4)))
(check-not-exn
(λ () (proceedings-location 'PLDI)))
(check-exn exn:fail:contract?
(λ () (proceedings-location "USENIX" #:pages "4--5"))))
(test-case "journal-location"
(check-not-exn
(λ () (journal-location "CACM" #:pages '(1 2) #:number 3 #:volume 4)))
(check-not-exn
(λ () (journal-location 'JFP)))
(check-exn exn:fail:contract?
(λ () (journal-location "Journal of Chromatography" #:pages 30))))
(test-case "book-location"
(check-not-exn
(λ () (book-location #:edition 1 #:publisher "A.C. Clayton")))
(check-not-exn
(λ () (book-location #:edition 'B #:publisher 'Elsiver)))
(check-exn exn:fail?
(λ () (book-location))))
(test-case "techrpt-location"
(check-not-exn
(λ () (techrpt-location #:institution "MIT" #:number 'AIM-353)))
(check-exn exn:fail:contract?
(λ () (techrpt-location #:institution 'UCB))))
(test-case "dissertation-location"
(check-not-exn
(λ () (dissertation-location #:institution "New College")))
(check-not-exn
(λ () (dissertation-location #:institution 'Oberlin)))
(check-not-exn
(λ () (dissertation-location #:institution "Georgetown University" #:degree "BS")))
(check-exn exn:fail:contract?
(λ () (dissertation-location #:degree "PhD"))))