4

I have two separated documents, compiled independently and residing in two completely different folders. I heavily rely on the chemnum package to assign numbers to the many molecules I have in both documents.

I would like to cross-reference this numbering system: if I create a compound label in document1 I would like document2 to recognise that such number has already been assigned and avoid the creation of a new label when \cmpd{...} is invoked in document2.

If the cross-referencing worked both ways (possibly using some sort of auxiliary file shared between the two documents) it would be even better.

I already triedxr, which seems to work fine for normal labels, i.e. the ones invoked by \label{...}but it doesn't seem to be compatible with chemnum entries in the aux files.

I know I could use \setchemnum{init} and define my compounds labels before using them but this defies the point of automatic labelling introduced by chemnum

Does anyone have any suggestions?

MWE:

document1.tex

\documentclass{article}
\usepackage{chemnum}

\begin{document}
\cmpd{compoundA, compoundB, compound C}

\end{document}

document2.tex

\documentclass{article}
\usepackage{chemnum}

\begin{document}
\cmpd{compoundB}

\end{document}

I would like document2 to print \cmpd{compoundB} as 2, not 1.

markellos
  • 461
  • 1
  • 4
  • 15

1 Answers1

4

Edit: (1) Added support for subcompunds, as requested by markellos. (2) Adjusted solution to support hyperref, see markellos' comment.

This very hacky solution builds upon xr's functionality and follows Ulrike Fischer's suggestion. This 'works' for the absolutely minimal working example you provided, but, depending on your use case, you might need to apply some adjustments.

Basically, we extend xr's scanning algorithm to recognize \chemnum@cmpd and \cmenum@subcmpd directives in the doc1.aux auxilliary file, and add those compounds to the compound list of doc2.tex.

doc1.tex:

\documentclass{article}
\usepackage{chemnum}

\begin{document}
\cmpd{compoundA,compoundB,compoundC.i,compoundC.ii}
\end{document}

doc2.tex:

\documentclass{article}

\usepackage{chemnum}
\usepackage{xr}

\makeatletter
\let\XR@oldread\XR@read
\def\XR@read{%
    \read\@inputcheck to\XR@line% identical to xr's definition
    \expandafter\XR@chemnumtest\XR@line...\XR@% here we inject our own parsing
    \expandafter\XR@test\XR@line...\XR@% continue with xr's parsing
}
\long\def\XR@chemnumtest#1#2#3#4\XR@{%
   \ifx#1\chemnum@cmpd
     \labelcmpd{#2}% this declares the compound locally
   \fi
   \ifx#1\chemnum@subcmpd
     \labelcmpd{#2.#3}% handles subcompounds
   \fi
}
\makeatother

% this reads doc1.aux
\externaldocument{doc1}

\begin{document}
\cmpd{compoundB,compoundC.i,compoundC.iii,compoundD}

\end{document}

After four compilations (pdflatex doc1.tex twice, then pdflatex doc2.tex twice), doc1.pdf shows "1, 2, 3a and 3b", and doc2.pdf shows "2, 3a, 3c and 4", as expected.

aehrm
  • 608
  • That's exactly what I was looking for, thanks! I had done the same a part from using \cmpd*{#2} instead of \cmpd{#2}. In fact I don't get why did this, even if I recognise it does the job. Also, I was try to extend the hack to allow xr to read \chemnum@subcmpd entries. These are generated by invoking commands like \cmpd{compoundA.sublabel1} and produce sublabels by storing the part after the dot between the second set of parentheses like this: \chemnum@subcmpd{compoundA}{sublabel1}. Unfortunately xr reads just the content of the first parentheses. How do we extend it to the second? Cheers. – markellos Jun 25 '18 at 22:34
  • @markellos I've added support for subcompounds, I hope this answers your question. – aehrm Jun 26 '18 at 14:06
  • Tthe hack doesn't work if hyperref is loaded, but just if your hack is inserted. Any idea how to fix it? xr clashes with this bit in the aux \HyperFirstAtBeginDocument{\AtBeginDocument} \HyperFirstAtBeginDocument{\ifx\hyper@anchor\@undefined \global\let\oldcontentsline\contentsline \gdef\contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}} \global\let\oldnewlabel\newlabel \gdef\newlabel#1#2{\newlabelxx{#1}#2} \gdef\newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}} \AtEndDocument{\ifx\hyper@anchor\@undefined \let\contentsline\oldcontentsline \let\newlabel\oldnewlabel \fi} \fi} – markellos Jun 26 '18 at 20:25
  • @markellos I've adjusted my solution to support hyperref. Nontheless, I restrained on extending the example files in order to keep the MWE minimal. Furthermore, I remind you that hyperref and xr are incompatible, and xr-hyper is required. (See also this answer concerning xr-hyper). – aehrm Jun 27 '18 at 00:30
  • Thank you very much. I marked your answer as accepted. One last thing. In my real document I use \addcontentsline{toc}{section}{Compound \cmpd+{compoundA.sublabel1}}. When I have sublabels imported with ´xr´the TOC prints n??, as if the labels weren't defined. How do I fix this? And sorry for bugging you with new questions every time. – markellos Jun 27 '18 at 12:31
  • @markells This semms to be an issue in chemnum's implementation: While pre-declaring compounds using \cmpd* in the preamble works fine, it fails for subcompounds, even without xr. (Exactly as you observed: n was resolved, the subcompound component remained unresolved as ??). As a temporary fix, you can move the \externaldocument after \begin{document}. Note that this also is going to copy all compounds of doc1 to the aux of doc2. – aehrm Jun 27 '18 at 16:59
  • If I move \externaldocumentafter \begin{document}LaTex complains and tells me that command can only be used in the preamble. Also, it screws up all the other labels in the document (non just compounds). So I'll wait and see if someone else comes up with a solution... In the meanwhile, thanks! – markellos Jun 27 '18 at 18:52