# chemidentifier

*[English version](README.md)*

Paquetage LaTeX pour numéroter les composés d'un article de chimie de
synthèse dans **l'ordre logique de la synthèse** — l'ordre où vous les
déclarez — et non dans l'ordre où ils apparaissent dans le texte.
Chaque numéro imprimé est cliquable et renvoie au schéma qui montre le
composé.

Écrit en LaTeX3 (expl3). Comme `\ref`/`\label`, tout se stabilise en
**deux compilations**.

La version 2 est celle chargée par défaut ; la version 1 est figée et
reste disponible pour les documents écrits avec elle :

```latex
\usepackage{chemidentifier}             % version 2
\usepackage[version=1]{chemidentifier}  % version 1, figée
```

## Installation

```sh
make install          # dans ~/texmf
make install TEXMF=/chemin/vers/texmf
```

Ou, plus simplement, copiez `chemidentifier.sty` à côté de votre document.

## En trois commandes

| Commande | Rôle | Affichage |
|---|---|---|
| `\chemid*{clé}` | déclaration | aucun |
| `\chemid{clé}` | utilisation | le numéro, cliquable |
| `\chemidhere{clé}` | ancre | aucun |
| `\chemidfamily{clé}{options}` | famille à gabarit | aucun |

```latex
\usepackage{hyperref}          % de préférence avant
\usepackage{chemidentifier}

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

\begin{document}
Le composé \chemid{benz} donne \chemid{benz.cl,benz.br}, puis \chemid{cible}.

\begin{figure}
  \includegraphics{schema}
  \chemidhere{benz}              % le parent et ses enfants d'un coup
  \caption{Halogénation de \chemid{benz}}
\end{figure}
\end{document}
```

## Règles d'affichage

| Appel | Résultat |
|---|---|
| `\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 et 2a` |
| `\chemid{cible}` | `cible_finale` |
| `\chemid{inconnue}` | `??` + erreur |

Le contexte est pris en compte automatiquement : lien cliquable dans le
texte, les légendes et les titres affichés ; **pas** de lien dans la
table des matières ni la liste des figures (l'entrée est déjà un lien
vers la section) ; texte brut dans les signets PDF.

## Options

Au chargement ou 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` ne se donne qu'au chargement : c'est la seule option lue par
le chargeur.

## Ancres et liens

`\chemidhere{clé}` pose la cible du lien, dans la figure qui montre le
composé. Elle accepte une liste, et nommer un **parent** ancre toute la
famille :

```latex
\chemidhere{cmbr.4,cmbr.6,cmbr.8}   % trois clés, trois ancres
\chemidhere{cmbr}                   % les mêmes trois, plus cmbr
\chemidhere{cmbr,cmal}              % deux familles en un appel
```

Un enfant qui porte une ancre à lui l'emporte, sans avertissement ;
`anchor-children=false` limite `\chemidhere{parent}` au parent seul.

**Un composé sans ancre n'est pas un lien.** Plutôt que de renvoyer
dans le vide, son numéro est imprimé tel quel (`strict-anchors`, actif
par défaut) — les ancres passant par le `.aux`, les liens se stabilisent
à la deuxième compilation. Si un parent n'est pas ancré mais que ses
enfants le sont, `\chemid{parent}` pointe vers le premier enfant ancré.
`strict-anchors=false` rétablit le comportement de la version 1, et
`links=false` supprime tout : aucun lien, aucune ancre, et plus aucun
avertissement d'ancre manquante.

`\herechemid` était le nom de la version 1 : il fonctionne toujours, et
signale une fois par document qu'il a été renommé.

## Familles à gabarit

Quand les membres d'une série se distinguent par quelque chose que le
chimiste nomme déjà — longueur de chaîne, degré d'oxydation,
substituant — le parent porte le radical et chaque enfant ne porte que
ce qui varie :

```latex
\chemidfamily{lcoum}{ name = Lcoum-C , placeholder = n }
  \chemid*{lcoum.quatre}{4}
  \chemid*{lcoum.huit}{8}
  \chemid*{lcoum.douze}{12}
```

| Appel | Résultat |
|---|---|
| `\chemid{lcoum.quatre}` | Lcoum-C₄ |
| `\chemid{lcoum.quatre,lcoum.huit}` | Lcoum-C₄,₈ |
| `\chemid{lcoum}` | Lcoum-Cₙ |

Le radical est imprimé une fois pour tout un groupe, exactement comme
`1a,b` factorise le `1`, et chaque valeur garde son lien.

Options : `name`, `raw`, `sub-style`, `child-format` (`subscript` par
défaut, `superscript`, `plain`, ou du code contenant `\chemidvalue`),
`placeholder`, `placeholder-raw`.

Un enfant déclaré sans valeur est numéroté par le `sub-style` de la
famille, `lower-greek` compris :

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

Les enfants numérotés automatiquement se contractent en intervalle ; les
valeurs données à la main, jamais (`4-12` affirmerait ce que personne
n'a écrit). Dans une famille, soit tous les enfants portent une valeur,
soit aucun : mélanger les deux est une erreur.

## Documents multilingues (babel)

Par défaut (sans babel, ou hors document multilingue), le séparateur
avant le dernier élément est l'anglais `and` (`last-sep`). Pour le
choisir vous-même :

```latex
\usepackage[last-sep={~et~}]{chemidentifier}   % au chargement
\chemidsetup{last-sep={~et~}}                  % ou à tout moment
```

Avec `babel`, le séparateur suit automatiquement la langue courante
fixée par `\selectlanguage` — utile pour une thèse mêlant des parties en
plusieurs langues :

```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 ...
```

Cinq langues sont connues par défaut, avec leurs variantes babel
usuelles : `english` (`american`, `british`, `australian`, `UKenglish`,
`USenglish`), `french` (`francais`, `acadian`, `canadien`), `german`
(`ngerman`, `austrian`, `naustrian`), `spanish` (`mexican`), `italian`.
`\chemidaddlanguage{langue}{séparateur}` ajoute ou redéfinit une entrée,
par exemple `\chemidaddlanguage{french}{ ou }`.

Sans `babel`, ou pour une langue non enregistrée, le paquetage retombe
sur `last-sep`. `auto-lang=false` désactive la bascule automatique pour
ne garder que `last-sep`, y compris localement dans un groupe.

La convention des revues de chimie (numéros en gras) :

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

Le manuel complet est dans `doc/chemidentifier-doc.pdf` (`make doc`).

## Diagnostics

Le paquetage signale : clé non déclarée, clé déclarée deux fois, clé à
plus d'un niveau, clé malformée, ancre posée deux fois, ancre sur une
clé inconnue, parent créé implicitement, composé utilisé sans ancre
(en fin de compilation), absence de `hyperref`, `\herechemid` employé
pour `\chemidhere`, et, pour les familles : clé qui n'est pas un
parent, famille déclarée deux fois, option de famille inconnue, valeurs
données et automatiques mélangées.

## Tests

```sh
make test              # 19 vérifications, avec pdflatex
make test-all          # les mêmes, avec pdflatex, lualatex et xelatex
make update-refs       # régénère les références (à relire avant de committer)
```

Les PDF produits sont conservés dans `test/pdf/`, nommés
`<test>-<moteur>.pdf`, pour inspection visuelle.

La suite compare, pour chaque document de test, le texte extrait du PDF
et les messages du `.log` à des références figées. Elle vérifie en outre
deux propriétés structurelles :

- le décompte des cibles de toutes les annotations de lien du PDF, ce
  qui détecte l'apparition d'un lien parasite dans la table des
  matières ;
- qu'une ancre ne déplace aucun mot de la page, en comparant les boîtes
  de tous les mots avec et sans ancres (écart mesuré : 0,0000 pt sous
  pdflatex et lualatex, 0,0062 pt sous xelatex, soit un arrondi de
  placement).

Les dix documents de la version 1 sont compilés avec `version=1` et
comparés à leurs références d'origine : c'est ce qui garantit que la
version figée ne bouge pas. S'y ajoutent le décompte des liens de
plusieurs documents et le contenu des signets, seul endroit où le rendu
en texte brut est visible de l'extérieur.

Les trois moteurs donnent le même résultat ; seule l'extraction de texte
de xelatex diffère, les ligatures y étant rendues par un caractère
unique (`ffi` → `ﬃ`). Une référence propre à un moteur n'est créée que
lorsqu'elle diffère réellement de la référence commune.

## Déclarer plusieurs clés d'un coup

`\chemid*{clé1,clé2,...}` déclare chacune, auto-numérotée à son tour —
même convention que `\chemid` :

```latex
\chemid*{mol1,mol2,mol3}     % trois parents : 1, 2, 3
\chemid*{mol1.a,mol1.b}      % deux enfants de mol1 : 1a, 1b
```

Un nom personnalisé ne peut pas accompagner une déclaration multiple
(`\chemid*{a,b}{nom}` serait ambigu) — erreur, déclarez cette clé seule.
Une virgule à l'intérieur d'une seule clé est rejetée. Déclarer des
enfants en bloc sans jamais déclarer leur parent à part fonctionne
aussi : le parent est créé implicitement, et `\chemid{molz}` (son nom
seul) affiche son numéro sans erreur.

## Déclarer après avoir utilisé

`\chemid`/`\chemidhere` peuvent apparaître **avant** le `\chemid*` qui
déclare la clé — comme un `\ref` avant son `\label`. La première
compilation affiche `??` (l'`.aux` est encore vide) ; la deuxième
résout, et le résultat reste stable ensuite, l'ordre des déclarations
ne dépendant jamais de l'endroit où elles sont utilisées :

```latex
Le composé \chemid{mol1} est présenté ici, mais déclaré plus loin.
...
\chemid*{mol1}
```

Une déclaration en tête de préambule reste néanmoins ce qu'il y a de
plus simple si vous n'avez pas de contrainte particulière : le numéro
est connu dès la lecture de la clé, sans référence en avant à
résoudre.

## Substitution de texte dans les figures .pdf_tex (LuaLaTeX uniquement)

Un schéma exporté par Inkscape (une paire `.pdf_tex` + `.pdf`) peut
avoir ses étiquettes de composés reliées à `\chemid`, comme `psfrag`
rustinait autrefois du texte dans des figures `.eps` — sans les
scories du `.eps`/psfrag : un `.pdf_tex` n'est que du texte LaTeX qui
appelle `\includegraphics`, donc une simple substitution ligne par
ligne suffit. Nécessite de compiler avec `lualatex` (ou tout autre
moteur fournissant `\directlua`) ; le fichier sur le disque n'est
jamais modifié, donc réexporter depuis Inkscape ne perd rien.

Placez dans le dessin un marqueur texte brut pour chaque étiquette de
composé (`TMP1`, `TMP2`... ce que vous voulez, tant qu'il n'apparaît
pas aussi comme sous-chaîne ailleurs dans le texte de la figure), puis :

```latex
\usepackage{graphicx}          % necessaire au .pdf_tex lui-meme
\usepackage{chemidentifier}
\chemidsetup{ pdftex-font = \sffamily\small }   % optionnel, une fois

\chemid*{precurseur}
\chemid*{produit}

\begin{figure}
  \centering
  \chemidkey{TMP1}{precurseur}               % TMP1 -> \chemid{precurseur}
  \chemidkey[1.3]{TMP2}{produit}             % 1,3x plus gros que le reste
  \chemidnote{TMPCOND}{K$_2$CO$_3$, acetone, 70~°C}
  \chemidscheme[0.8]{figures/schema.pdf_tex}   % echelle optionnelle
  \chemidhere{precurseur}\chemidhere{produit}
  \caption{Synthèse de \chemid{produit} à partir de \chemid{precurseur}.}
\end{figure}
```

| Commande | Rôle |
|---|---|
| `\chemidkey[facteur]{motif}{clé}` | marqueur → numéro courant du composé, ex. `\chemid{clé}` |
| `\chemidnote[facteur]{motif}{texte}` | marqueur → tout autre texte, libre |
| `\chemidscheme[échelle]{chemin}` | lit le fichier, substitue, compose ; étend aussi `\graphicspath` |

`\chemidscheme` consomme la liste `\chemidkey`/`\chemidnote` en
attente au fur et à mesure qu'il lit le fichier : la figure suivante
repart donc automatiquement d'une liste vide — pas d'étape « vider »
séparée à retenir.

La taille d'une étiquette substituée est le produit de trois facteurs
indépendants, pour qu'une figure réduite reste lisible sans retoucher
chaque étiquette à la main :

1. **`pdftex-font`** (`\chemidsetup`) — la police de base, réglée une
   fois pour toutes, indépendamment du texte du corps (sinon Inkscape
   réinjecte la famille du document, à la taille du dessin, souvent
   trop grande), ex.
   `\chemidsetup{ pdftex-font = \sffamily\fontsize{9}{11}\selectfont }`.
2. **l'`[échelle]` de `\chemidscheme`** — le même nombre transmis au
   `\svgscale` de la figure, pour que les étiquettes suivent la taille
   du dessin.
3. **le `[facteur]` optionnel de `\chemidkey`/`\chemidnote`** — une
   étiquette isolée par rapport aux autres de la même figure ; vaut
   `1` par défaut.

Sous un moteur non-Lua, `\chemidscheme` déclenche une erreur claire
plutôt que de ne rien faire silencieusement. `\chemidkey` prend le
numéro *courant* du composé : elle ne déclare ni ne renumérote rien,
les clés doivent donc toujours avoir leur `\chemid*{clé}` déclaré par
ailleurs.

*Pourquoi LuaLaTeX seulement ?* Une alternative en TeX pur, à base de
manipulation de catcodes (à la `psfrag`), a été envisagée puis
écartée : un `.pdf_tex` est du vrai code TeX/PGF, plein de `\`, `{`,
`}`, `%`, `#`, `_`, `~`... Le lire tel quel puis le ré-exécuter comme
du code demanderait qu'un même caractère porte deux catcodes
contradictoires — inerte pendant la lecture, actif pendant
l'exécution — pour un contenu arbitraire : exactement ce qui rendait
`psfrag` fragile. Lua contourne le problème en traitant le fichier
comme une simple chaîne de bout en bout, et ne rend la main à TeX qu'à
la toute fin, lu alors sous le régime de catcodes ordinaire du
document.

## Limites assumées

- Un seul niveau de hiérarchie (`parent.enfant`), familles comprises.
- Les listes ne sont ni triées ni dédoublonnées : `\chemid{a,b,a}`
  affiche `1, 2 et 1`, sans erreur.
- `cleveref` n'est pas géré.
- Si une clé est supprimée du document, une référence qui y pointe
  encore continue de se résoudre à sa dernière valeur connue tant que
  l'`.aux` n'a pas été effacé — la même limite que `\ref`/`\label`.

## Auteur et licence

Aliocha SKRZYPCZAK <aliochask.pro@gmail.com>

Ce travail peut être distribué et/ou modifié selon les conditions de
la LaTeX Project Public License, version 1.3c de cette licence ou (à
votre choix) toute version ultérieure. Ce travail a le statut de
maintenance LPPL « maintained ». Voir `LICENSE` pour le texte complet.
