Skip to content

Commit

Permalink
Prevent duplicate labels in :alpha style
Browse files Browse the repository at this point in the history
This implements a stateful `AlphaStyle` that disambiguates the labels
for the bibliography by appending a suffix "a", "b", etc. This emulates
the behavior of the numeric citation style in LaTeX.

To enable the generating of unique labels, there is a new internal
`init_bibliography!` function that is called at the beginning of the
`ExpandBibliography` pipeline step.

The existing `:alpha` style is automatically upgraded to the new
`AlphaStyle`. It's just easier for users to pass `style=:alpha` than to
instantiate the full `AlphaStyle`. Moreover, there's no reason anyone
would ever want to use the old "dumb" `:alpha` style.

In addition to the new `AlphaStyle`, this also fixes some
inconsistencies relative to the alphabetic citation style in LaTeX:

* Up to four names are included in the label, not 3 (but 5 or more names
  results in 3 names and "+")
* The first letter of a "particle" of the name is included in the label,
  e.g. "vWB08" for a first author "von Winckel"
  • Loading branch information
goerz committed Sep 4, 2023
1 parent 8bdabbd commit e4ec55c
Show file tree
Hide file tree
Showing 15 changed files with 426 additions and 27 deletions.
16 changes: 16 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,22 @@
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Fixed

* Do not try include a year when rendering a reference if the underlying BibTeX entry has no `year` field.
* Avoid duplicate labels in `:alpha` style. This is implemented via the new stateful `AlphaStyle()`, but is handled automatically.
* With the alphabetic style (`:alpha`/`AlphaStyle`), include up to 4 names in the label, not 3 (but 5 or more names results in 3 names and "+"). Also, include the first letter of a "particle" in the label, e.g. "vWB08" for a first author "von Winckel". Both of these are consistent with LaTeX's behavior.

### Added

* New `style=AlphaStyle()` that generates unique citation labels. This can mostly be considered internal, as `style=:alpha` is automatically upgraded to `style=AlphaStyle()`.

### Internal Changes

* Added an internal function `init_bibliography!` that is called at the beginning of the `ExpandBibliography` pipeline step. This function is intended to initialized internal state either of the `style` object or the `CitationBibliography` plugin object before rendering any `@bibliography` blocks. This is used to generate unique citation labels for the new `AlphaStyle()`. For the other builtin styles, it is a no-op. Generally, `init_bibliography!` can help with implementing custom "stateful" styles.


## [Version v1.0.0][1.0.0] - 2023-07-12

Expand Down
8 changes: 7 additions & 1 deletion docs/latex/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.PHONY: all clean

ALL = numeric.pdf authoryear.pdf rmp.pdf prb.pdf
ALL = numeric.pdf authoryear.pdf rmp.pdf prb.pdf alpha.pdf

all: $(ALL)

Expand Down Expand Up @@ -28,6 +28,12 @@ prb.pdf: prb.tex
pdflatex $<
pdflatex $<

alpha.pdf: alpha.tex
pdflatex $<
bibtex $(basename $<)
pdflatex $<
pdflatex $<

clean:
@rm -f ${ALL}
@rm -f *.aux
Expand Down
63 changes: 63 additions & 0 deletions docs/latex/alpha.tex
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
\documentclass[aps,pra,onecolumn,noshowpacs,superscriptaddress,preprintnumbers,%
kamsmath,amssymb,notitlepage,letterpaper]{revtex4-2}

\def\Author{Michael Goerz}
\def\Title{Demo of the standard RevTeX numeric citation style}

\usepackage{natbib}
\usepackage[utf8]{inputenc}
\usepackage{caption}
\captionsetup{justification=raggedright, singlelinecheck=true}
\usepackage[
pdftitle={\Title},
pdfauthor={\Author},
colorlinks=true, linkcolor=black, urlcolor=black, citecolor=black,
bookmarksopen=false, breaklinks=true, plainpages=false, pdfpagelabels
]{hyperref}

\begin{document}

\title{\Title}
\author{\Author}
\date{\today}

\maketitle

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{itemize}
\item \verb|\cite{GoerzQ2022}| renders as ``\cite{GoerzQ2022}''.
\item \verb|\citet{GoerzQ2022}| renders as ``\citet{GoerzQ2022}''.
\item \verb|\citep{GoerzQ2022}| renders as ``\citep{GoerzQ2022}''.
\item \verb|\cite[Eq.~(1)]{GoerzQ2022}| renders as ``\cite[Eq.~(1)]{GoerzQ2022}''.
\item \verb|\citet[Eq.~(1)]{GoerzQ2022}| renders as ``\citet[Eq.~(1)]{GoerzQ2022}''.
\item \verb|\citep[Eq.~(1)]{GoerzQ2022}| renders as ``\citep[Eq.~(1)]{GoerzQ2022}''.
\item \verb|\citet*{GoerzQ2022}| renders as ``\citet*{GoerzQ2022}''.
\item \verb|\citep*{GoerzQ2022}| renders as ``\citep*{GoerzQ2022}''.
\item \verb|\citet*[Eq.~(1)]{GoerzQ2022}| renders as ``\citet*[Eq.~(1)]{GoerzQ2022}''.
\item \verb|\citep*[Eq.~(1)]{GoerzQ2022}| renders as ``\citep*[Eq.~(1)]{GoerzQ2022}''.
\item \verb|\citet{WinckelIP2008}| renders as ``\citet{WinckelIP2008}''.
\item \verb|\Citet{WinckelIP2008}| renders as ``\Citet{WinckelIP2008}''.
\item \cite{GraceJMO2007}, \cite{GraceJPB2007}, \cite{GrondPRA2009a}, and \cite{GrondPRA2009b}
\end{itemize}

Further commands that we do not support in markdown:

\begin{itemize}
\item \verb|\citenum{GoerzQ2022}| renders as ``\citenum{GoerzQ2022}''.
\item \verb|\citealt{GoerzQ2022}| renders as ``\citealt{GoerzQ2022}''.
\item \verb|\citealp{GoerzQ2022}| renders as ``\citealp{GoerzQ2022}''.
\item \verb|\citealt*{GoerzQ2022}| renders as ``\citealt*{GoerzQ2022}''.
\item \verb|\citealp*{GoerzQ2022}| renders as ``\citealp*{GoerzQ2022}''.
\item \verb|\citealt*[Eq.~(1)]{GoerzQ2022}| renders as ``\citealt*[Eq.~(1)]{GoerzQ2022}''.
\item \verb|\citealp*[Eq.~(1)]{GoerzQ2022}| renders as ``\citealp*[Eq.~(1)]{GoerzQ2022}''.
\item \verb|\Citealt{WinckelIP2008}| renders as ``\Citealt{WinckelIP2008}''.
\item \verb|\Citealp{WinckelIP2008}| renders as ``\Citealp{WinckelIP2008}''.
\end{itemize}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\bibliographystyle{alpha}
\bibliography{../src/refs}

\end{document}
18 changes: 18 additions & 0 deletions docs/src/gallery.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,24 @@ Style = :alpha
Canonical = false
```

Note that the `:alpha` style is able to automatically disambiguate labels:

```@bibliography
Pages = []
Style = :alpha
Canonical = false
GraceJMO2007
GraceJPB2007
```

This works because the `DocumenterCitations` automatically upgrades `style=:alpha` to the internal

```@docs
DocumenterCitations.AlphaStyle
```


## [Custom styles](@id custom_styles)

In the following, we show two examples for user-defined styles. See the [notes on customization](@ref customization) on how to generally define a custom style.
Expand Down
3 changes: 2 additions & 1 deletion docs/src/internals.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ ExpandCitations

## [Customization](@id customization)

A custom style can be created by defining methods for functions listed below that specialize for a user-defined `style` argument to [`CitationBibliography`](@ref). If the `style` is identified by a simple name, e.g. `:mystyle`, the method should specialize on `Val{:mystyle}`, see the [examples for custom styles](@ref custom_styles). Beyond that, e.g., if the `style` needs to implement options or needs to maintain internal state to manage unique citation labels, `style` can be an object of a custom type.
A custom style can be created by defining methods for the functions listed below that specialize for a user-defined `style` argument to [`CitationBibliography`](@ref). If the `style` is identified by a simple name, e.g. `:mystyle`, the methods should specialize on `Val{:mystyle}`, see the [examples for custom styles](@ref custom_styles). Beyond that, e.g., if the `style` needs to implement options or needs to maintain internal state to manage unique citation labels, `style` can be an object of a custom type. The builtin [`DocumenterCitations.AlphaStyle`](@ref) is an example for such a "stateful" style, initialized via a custom [`init_bibliography!`](@ref) method.


```@docs
Expand All @@ -36,6 +36,7 @@ bib_sorting
format_bibliography_label
format_bibliography_reference
format_citation
init_bibliography!
```

## Debugging
Expand Down
58 changes: 58 additions & 0 deletions docs/src/refs.bib
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,8 @@ @article{GoerzQ2022
Doi = {10.22331/q-2022-12-07-871},
Pages = {871},
Volume = {6},
eprint = {2205.15044},
Archiveprefix = {arXiv},
}

@article{RaithelQST2022,
Expand Down Expand Up @@ -427,3 +429,59 @@ @manual{SciPy
year = {2001--},
url = {https://docs.scipy.org/doc/scipy/},
}


@article{LapertPRA09,
Author = {Lapert, M. and Tehini, R. and Turinici, G. and Sugny, D.},
Title = {Monotonically Convergent Optimal Control Theory of Quantum Systems with Spectral Constraints on the Control Field},
Journal = pra,
Year = {2009},
Doi = {10.1103/PhysRevA.79.063411},
Pages = {063411},
Volume = {79},
}


@article{GraceJMO2007,
Author = {Grace, Matthew D. and Brif, Constantin and Rabitz, Herschel and Lidar, Daniel A. and Walmsley, Ian A. and Kosut, Robert L.},
Title = {Fidelity of optimally controlled quantum gates with randomly coupled multiparticle environments},
Journal = jmo,
Year = {2007},
Doi = {10.1080/09500340701639615},
Pages = {2339},
Volume = {54},
}


@article{GraceJPB2007,
Author = {Grace, Matthew and Brif, Constantin and Rabitz, Herschel and Walmsley, Ian A and Kosut, Robert L and Lidar, Daniel A},
Title = {Optimal control of quantum gates and suppression of decoherence in a system of interacting two-level particles},
Journal = jpb,
Year = {2007},
Doi = {10.1088/0953-4075/40/9/s06},
Pages = {S103},
Volume = {40},
}


@article{GrondPRA2009b,
Author = {Grond, Julian and von Winckel, Gregory and Schmiedmayer, J\"org and Hohenester, Ulrich},
Title = {Optimal control of number squeezing in trapped {Bose-Einstein} condensates},
Journal = pra,
Year = {2009},
Doi = {10.1103/PhysRevA.80.053625},
Pages = {053625},
Volume = {80},
}


@article{GrondPRA2009a,
Author = {Grond, Julian and Schmiedmayer, J\"org and Hohenester, Ulrich},
Title = {Optimizing number squeezing when splitting a mesoscopic condensate},
Journal = pra,
Year = {2009},
Doi = {10.1103/PhysRevA.79.021603},
Pages = {021603},
Volume = {79},
}

4 changes: 2 additions & 2 deletions docs/src/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ In `[…](@cite)`, the following variations can be used instead of `@cite`:

Lastly, capitalizing the `c` in `@citet` or `@citet*` ensures that the first letter of the citation is capitalized so that it can be used at the beginning of a sentence, e.g., [WinckelIP2008](@Citet) (`[WinckelIP2008](@Citet)`) versus [WinckelIP2008](@citet) (`[WinckelIP2008](@citet)`).

The [natbib](https://mirrors.rit.edu/CTAN/macros/latex/contrib/natbib/natnotes.pdf) commands `@citealt`, `@citealp`, and `@citenum` commands are also recognized. They are not supported by any of the built-in style, but may be handled by [custom styles](@ref customization).
The [natbib](https://mirrors.rit.edu/CTAN/macros/latex/contrib/natbib/natnotes.pdf) commands `@citealt`, `@citealp`, and `@citenum` commands are also recognized. They are not supported by any of the built-in styles, but may be handled by [custom styles](@ref customization).

See the [Citation Style Gallery](@ref gallery) for examples of all the possible combinations.

Expand Down Expand Up @@ -82,7 +82,7 @@ Renders a bibliography for *all* references included in the `.bib` file, not jus

### [Multiple `@bibliography` blocks](@id canonical)

It is possible to have multiple `@bibliography` blocks. However, there can only be one "canonical" bibliography target for any citation (the location where a citation links to). Any `@bibliography` block will automatically skip entries that have already been rendered in an earlier `@bibliography` block. Thus, for two consecutive
It is possible to have multiple `@bibliography` blocks. However, there can only be one "canonical" bibliography target for any citation (the location where a citation links to). Any `@bibliography` block will automatically skip entries that have already been rendered in an earlier canonical `@bibliography` block. Thus, for two consecutive

~~~markdown
```@bibliography
Expand Down
39 changes: 36 additions & 3 deletions src/DocumenterCitations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ using Documenter.Expanders
using Documenter.Writers.HTMLWriter

using Markdown
using Bibliography
using Bibliography: xyear, xlink, xtitle
using Bibliography: Bibliography, xyear, xlink, xtitle
using OrderedCollections: OrderedDict, OrderedSet
using Unicode

Expand Down Expand Up @@ -79,8 +78,12 @@ function CitationBibliography(bibfile::AbstractString=""; style=nothing, cached=
# The message is only to transition users through the breaking change
# in 1.0. It can be removed in any future 1.1 release.
style = :numeric
@debug "Using default style=$(repr(style))"
elseif style == :alpha
@debug "Auto-upgrading :alpha to AlphaStyle()"
style = AlphaStyle()
end
entries = import_bibtex(bibfile)
entries = Bibliography.import_bibtex(bibfile)
if length(bibfile) > 0
if !isfile(bibfile)
error("bibfile $bibfile does not exist")
Expand Down Expand Up @@ -115,6 +118,36 @@ in its docstring.
"""
struct Example end


"""
"Smart" alphabetic citation style (relative to the "dumb" `:alpha`).
```julia
style = AlphaStyle()
```
instantiates a style for [`CitationBibliography`](@ref) that avoids duplicate
labels. Any of the entries that would result in the same label will be
disambiguated by appending the suffix "a", "b", etc.
Any bibliography that cites a subset of the given `entries` is guaranteed to
have unique labels.
"""
struct AlphaStyle

# BibTeX key (entry.id) => rendered label, e.g. "GraceJMO2007" => "GBR+07b"
label_for_key::Dict{String,String}
# The internal field `label_for_key` is set by `init_bibliography!` at the
# beginning of the `ExpandBibliography` pipeline step.

AlphaStyle() = new(Dict{String,String}())

end


Base.show(io::IO, ::AlphaStyle) = print(io, "AlphaStyle()")


include("citations.jl")
include("bibliography.jl")
include("formatting.jl")
Expand Down
Loading

0 comments on commit e4ec55c

Please sign in to comment.