# chemidentifier

*[Version française](README.fr.md)*

LaTeX package to number the compounds of a synthesis-chemistry paper in
**the logical order of the synthesis** — the order in which you declare
them — rather than the order in which they appear in the text. Every
printed number is clickable and jumps to the scheme showing the
compound.

Written in LaTeX3 (expl3). Like `\ref`/`\label`, everything settles
over **two compilations**.

Version 2 is the one loaded by default; version 1 is frozen and stays
available for the documents written against it:

```latex
\usepackage{chemidentifier}             % version 2
\usepackage[version=1]{chemidentifier}  % version 1, frozen
```

## Installation

```sh
make install          # into ~/texmf
make install TEXMF=/path/to/texmf
```

Or, more simply, copy `chemidentifier.sty` next to your document.

## Three commands

| Command | Role | Output |
|---|---|---|
| `\chemid*{key}` | declaration | none |
| `\chemid{key}` | use | the number, clickable |
| `\chemidhere{key}` | anchor | none |
| `\chemidfamily{key}{options}` | templated family | none |

```latex
\usepackage{hyperref}          % preferably before
\usepackage{chemidentifier}

\chemid*{benz}                 % 1
\chemid*{benz.cl,benz.br}      % 1a, 1b -- multiple declaration
\chemid*{amine}                % 2
\chemid*{target}{target\textsubscript{final}}[final target]

\begin{document}
Compound \chemid{benz} gives \chemid{benz.cl,benz.br}, then \chemid{target}.

\begin{figure}
  \includegraphics{schema}
  \chemidhere{benz}              % the parent and its children at once
  \caption{Halogenation of \chemid{benz}}
\end{figure}
\end{document}
```

## Display rules

| Call | Result |
|---|---|
| `\chemid{benz}` | `1` |
| `\chemid{benz.cl}` | `1a` |
| `\chemid{benz.cl,benz.br,benz.i}` | `1a-c` |
| `\chemid{benz.cl,benz.br}` | `1a,b` |
| `\chemid{benz.cl,benz.i}` | `1a,1c` |
| `\chemid{benz,amine.a}` | `1 and 2a` |
| `\chemid{target}` | `final_target` |
| `\chemid{unknown}` | `??` + error |

Context is taken into account automatically: clickable link in the
text, captions and displayed titles; **no** link in the table of
contents or the list of figures (the entry is already a link to the
section); plain text in PDF bookmarks.

## Options

At load time, or via `\chemidsetup{...}`:

`list-sep`, `last-sep`, `sub-sep`, `range-sep`, `range-threshold`,
`format`, `main-style`, `sub-style` (+ `lower-greek`), `prefix`,
`unknown-text`, `purify`, `implicit-parent`, `strict-anchors`, `links`,
`anchor-children`, `auto-lang`.

`version` is load-time only: it is the single option the loader reads.

## Anchors and links

`\chemidhere{key}` places the target of the link, in the figure showing
the compound. It takes a list, and naming a **parent** anchors the whole
family:

```latex
\chemidhere{cmbr.4,cmbr.6,cmbr.8}   % three keys, three anchors
\chemidhere{cmbr}                   % the same three, plus cmbr itself
\chemidhere{cmbr,cmal}              % two families in one call
```

A child carrying an anchor of its own wins, silently;
`anchor-children=false` keeps `\chemidhere{parent}` to the parent alone.

**A compound with no anchor is not a link.** Rather than point at
nothing, its number is printed as it is (`strict-anchors`, on by
default) — anchors travelling through the `.aux`, links settle on the
second compilation. If a parent is not anchored but its children are,
`\chemid{parent}` goes to the first anchored child.
`strict-anchors=false` restores version 1's behaviour, and
`links=false` drops everything: no link, no anchor, and no
missing-anchor warning left.

`\herechemid` was version 1's name for it: it still works, and says once
per document that it has been renamed.

## Templated families

When the members of a series are told apart by something the chemist
already has a name for — chain length, oxidation state, substituent —
the parent holds the stem and each child carries only what varies:

```latex
\chemidfamily{lcoum}{ name = Lcoum-C , placeholder = n }
  \chemid*{lcoum.four}{4}
  \chemid*{lcoum.eight}{8}
  \chemid*{lcoum.twelve}{12}
```

| Call | Result |
|---|---|
| `\chemid{lcoum.four}` | Lcoum-C₄ |
| `\chemid{lcoum.four,lcoum.eight}` | Lcoum-C₄,₈ |
| `\chemid{lcoum}` | Lcoum-Cₙ |

The stem is printed once for a whole group, exactly as `1a,b` factors
out the `1`, and every value keeps its own link.

Options: `name`, `raw`, `sub-style`, `child-format` (`subscript` by
default, `superscript`, `plain`, or code containing `\chemidvalue`),
`placeholder`, `placeholder-raw`.

A child declared with no value is numbered by the family's `sub-style`,
`lower-greek` included:

```latex
\chemidfamily{ser}{ name = Series , sub-style = lower-greek , child-format = plain }
  \chemid*{ser.a}\chemid*{ser.b}\chemid*{ser.c}
% \chemid{ser.a,ser.b,ser.c}  ->  Seriesα-γ
```

Automatically numbered children contract into a range; values given by
hand never do (`4-12` would claim something nobody wrote). Inside one
family, either every child carries a value or none does: mixing the two
is an error.

## Multilingual documents (babel)

By default (without babel, or outside a multilingual document), the
separator before the last item is the English `and` (`last-sep`). To
choose it yourself:

```latex
\usepackage[last-sep={~and~}]{chemidentifier}   % at load time
\chemidsetup{last-sep={~and~}}                  % or at any time
```

With `babel`, the separator automatically follows the current language
set by `\selectlanguage` — useful for a thesis mixing several
languages:

```latex
\usepackage[french,ngerman,spanish,italian,english]{babel}
...
\selectlanguage{french}   \chemid{a,b}   % ... et ...
\selectlanguage{ngerman}  \chemid{a,b}   % ... und ...
\selectlanguage{spanish}  \chemid{a,b}   % ... y ...
\selectlanguage{italian}  \chemid{a,b}   % ... e ...
\selectlanguage{english}  \chemid{a,b}   % ... and ...
```

Five languages are known by default, with their usual babel variants:
`english` (`american`, `british`, `australian`, `UKenglish`,
`USenglish`), `french` (`francais`, `acadian`, `canadien`), `german`
(`ngerman`, `austrian`, `naustrian`), `spanish` (`mexican`), `italian`.
`\chemidaddlanguage{language}{separator}` adds or redefines an entry,
for example `\chemidaddlanguage{french}{ ou }`.

Without `babel`, or for an unregistered language, the package falls
back to `last-sep`. `auto-lang=false` disables the automatic switch to
keep only `last-sep`, including locally inside a group.

The chemistry-journal convention (bold numbers):

```latex
\usepackage[format=\textbf]{chemidentifier}
```

The full manual is in `doc/chemidentifier-doc.pdf` (`make doc`).

## Diagnostics

The package reports: undeclared key, key declared twice, key with more
than one level, malformed key, anchor placed twice, anchor on an
unknown key, implicitly created parent, compound used without an
anchor (at the end of compilation), missing `hyperref`, `\herechemid`
used for `\chemidhere`, and, for families: key that is not a parent,
family declared twice, unknown family option, given and automatic
values mixed.

## Tests

```sh
make test              # 19 checks, with pdflatex
make test-all          # the same, with pdflatex, lualatex and xelatex
make update-refs       # regenerates the references (review before committing)
```

The produced PDFs are kept in `test/pdf/`, named `<test>-<engine>.pdf`,
for visual inspection.

For each test document, the suite compares the text extracted from the
PDF and the messages from the `.log` against frozen references. It
also checks two structural properties:

- the target count of every link annotation in the PDF, which detects
  a stray link showing up in the table of contents;
- that an anchor never shifts any word on the page, by comparing the
  boxes of every word with and without anchors (measured deviation:
  0.0000 pt under pdflatex and lualatex, 0.0062 pt under xelatex, a
  placement rounding).

The ten version 1 documents are compiled with `version=1` and compared
against their original references: that is what guarantees the frozen
version does not move. Added to them are the link count of several
documents and the content of the bookmarks, the only place the
plain-text rendering shows from the outside.

The three engines give the same result; only xelatex's text extraction
differs, ligatures being rendered there as a single character (`ffi` →
`ﬃ`). An engine-specific reference is only created when it actually
differs from the common reference.

## Declaring several keys at once

`\chemid*{key1,key2,...}` declares each of them, auto-numbered in
turn — the same convention as `\chemid`:

```latex
\chemid*{mol1,mol2,mol3}     % three parents: 1, 2, 3
\chemid*{mol1.a,mol1.b}      % two children of mol1: 1a, 1b
```

A custom name cannot accompany a multiple declaration
(`\chemid*{a,b}{name}` would be ambiguous) — error, declare that key
on its own. A comma inside a single key is rejected. Declaring
children in bulk without ever declaring their parent on its own also
works: the parent is created implicitly, and `\chemid{molz}` (its name
alone) prints its number without error.

## Declaring after using

`\chemid`/`\chemidhere` may appear **before** the `\chemid*` that
declares the key — like a `\ref` before its `\label`. The first
compilation shows `??` (the `.aux` is still empty); the second
resolves it, and the result stays stable afterwards, the order of
declarations never depending on where they are used:

```latex
Compound \chemid{mol1} is introduced here, but declared further down.
...
\chemid*{mol1}
```

A declaration at the top of the preamble nonetheless remains the
simplest approach if you have no particular constraint: the number is
then known as soon as the key is read, with no forward reference to
resolve.

## Text substitution in .pdf_tex figures (LuaLaTeX only)

A scheme exported by Inkscape (a `.pdf_tex` + `.pdf` pair) can have its
compound labels wired to `\chemid`, the same way `psfrag` once patched
text into `.eps` figures — without the `.eps`/`psfrag` baggage: a
`.pdf_tex` is just LaTeX text calling `\includegraphics`, so a plain,
line-by-line substitution done in Lua is enough. Requires compiling
with `lualatex` (or another engine providing `\directlua`); the file on
disk is never modified, so re-exporting from Inkscape loses nothing.

Put a plain-text placeholder in the drawing for each compound label
(`TMP1`, `TMP2`... anything, as long as it does not also occur as a
substring elsewhere in the figure text), then:

```latex
\usepackage{graphicx}          % needed by the .pdf_tex itself
\usepackage{chemidentifier}
\chemidsetup{ pdftex-font = \sffamily\small }   % optional, once

\chemid*{precursor}
\chemid*{product}

\begin{figure}
  \centering
  \chemidkey{TMP1}{precursor}               % TMP1 -> \chemid{precursor}
  \chemidkey[1.3]{TMP2}{product}            % 1.3x bigger than the rest
  \chemidnote{TMPCOND}{K$_2$CO$_3$, acetone, 70~°C}   % free text
  \chemidscheme[0.8]{figures/scheme.pdf_tex}   % scale is optional
  \chemidhere{precursor}\chemidhere{product}
  \caption{Synthesis of \chemid{product} from \chemid{precursor}.}
\end{figure}
```

| Command | Role |
|---|---|
| `\chemidkey[factor]{motif}{key}` | placeholder → the compound's current number, e.g. `\chemid{key}` |
| `\chemidnote[factor]{motif}{text}` | placeholder → any other text, free-form |
| `\chemidscheme[scale]{path}` | reads the file, substitutes, typesets; also adds its folder to `\graphicspath` |

`\chemidscheme` consumes the pending `\chemidkey`/`\chemidnote` list as
it reads the file, so the next figure automatically starts from an
empty list — there is no separate "clear" step to remember.

The size of a substituted label is the product of three independent
factors, so a figure scaled down still reads fine without retouching
every label by hand:

1. **`pdftex-font`** (`\chemidsetup`) — the base style, set once,
   independently of the body text (Inkscape otherwise reinjects the
   document's own family, at whatever size the drawing used, typically
   too large), e.g.
   `\chemidsetup{ pdftex-font = \sffamily\fontsize{9}{11}\selectfont }`.
2. **the `[scale]` of `\chemidscheme`** — the same number handed to the
   figure's own `\svgscale`, so labels shrink/grow together with the
   drawing.
3. **the optional `[factor]` of `\chemidkey`/`\chemidnote`** — one
   label singled out, relative to the others in the same figure;
   defaults to `1`.

Under a non-Lua engine, `\chemidscheme` raises a clear error instead of
silently doing nothing. `\chemidkey` takes the compound's *current*
number: it does not declare or renumber anything, so keys still need a
matching `\chemid*{key}` elsewhere.

*Why LuaLaTeX only?* A pure-TeX, catcode-trick alternative (à la
`psfrag`) was considered and rejected: a `.pdf_tex` is genuine TeX/PGF
code, full of `\`, `{`, `}`, `%`, `#`, `_`, `~`... Reading it verbatim
and then re-executing it as code would require the same character to
carry two contradictory catcodes — inert while captured, active while
replayed — for arbitrary content, which is exactly what made `psfrag`
fragile. Lua sidesteps this entirely by treating the file as a plain
string throughout, and handing the result back to TeX only at the very
end, read under the document's own, ordinary catcode regime.

## Assumed limitations

- A single level of hierarchy (`parent.child`), families included.
- Lists are neither sorted nor deduplicated: `\chemid{a,b,a}` prints
  `1, 2 and 1`, without error.
- `cleveref` is not handled.
- If a key is removed from the document, a reference that still
  points to it keeps resolving to its last known value until the
  `.aux` file is cleared — the same limitation as `\ref`/`\label`.

## Author and license

Aliocha SKRZYPCZAK <aliochask.pro@gmail.com>

This work may be distributed and/or modified under the conditions of
the LaTeX Project Public License, either version 1.3c of this license
or (at your option) any later version. This work has the LPPL
maintenance status `maintained`. See `LICENSE` for the full text.
