4

I'm likely ignoring something fundamental here and was hoping for some hints. Please see the inset mwe.

Towards having a library of chemfig symbols, I see value in being able to point to a particular symbol (stored in an external .tex file) via the \input{} command, the obvious construct being: \chemfig[][]{\input{<chemfig symbol library path>/{<symbol name>}}}.

\documentclass[preview,border=7pt,active,tightpage]{standalone}
\usepackage{booktabs}
\usepackage{chemfig}
\usepackage{filecontents} 
\usepackage[scaled]{helvet}

%\begin{filecontents}{methane.tex}
%H% 2
%    -[:210]% 1
%              (
%        -[:210]H% 3
%              )
%              (
%        -[:300]H% 5
%              )
%    -[:120]H% 4
%\end{filecontents}

% representation without comments
\begin{filecontents}{methane.tex}
H
    -[:210]
              (
        -[:210]H
              )
              (
        -[:300]H
              )
    -[:120]H
\end{filecontents}

\DeclareRobustCommand{\robustinputcommand}{\input{methane.tex}}

% sans serif font
\renewcommand\familydefault{\sfdefault} 

% define formulae
\def\methane{\mathrm{CH_{4}}}

\begin{document}
\begin{center}
\begin{tabular}[]{lp{1.5cm}}
\toprule
\textbf{Formula} & \textbf{Structure}\\
\midrule%
%$\methane$ & \begin{minipage}[]{1cm} \chemfig{\input{methane.tex}} \end{minipage} \\ [2mm]% gives error
%$\methane$ & \begin{minipage}[]{1cm} \chemfig{\protect\input{methane.tex}} \end{minipage} \\ [2mm]% gives error
%$\methane$ & \begin{minipage}[]{1cm} \chemfig{\robustinputcommand} \end{minipage} \\ [2mm]% gives error
\bottomrule
\end{tabular}
\end{center}
\end{document}

Here is the error I observe consistently:

! Undefined control sequence.
<everyeof> \_nil 

I have tried a few approaches, particularly those described here. These are commented in the mwe.

Note that the construct: \input{<full file path>} (document level call) and \chemfig[][]{<content defining symbol>} (generic structure of external document) works fine, but this does not immediately allow one to apply formatting e.g. [scale=0.5] as optional argument of \chemfig at the document level - something there is clear value in being able to do.

1
  • Maybe consider using chemfig's submol mechanism instead. In this way, you can keep multiple molecules in the same library file. Commented Aug 3, 2019 at 21:04

3 Answers 3

2

Here is a \chemfiginput command that also accepts the optional argument like \chemfig.

% representation without comments
\begin{filecontents}{methane.tex}
H
    -[:210]
              (
        -[:210]H
              )
              (
        -[:300]H
              )
    -[:120]H
\end{filecontents}

\documentclass{article}
\usepackage{booktabs}
\usepackage{chemfig}
\usepackage[scaled]{helvet}
\usepackage{catchfile}


% sans serif font
\renewcommand\familydefault{\sfdefault} 

% define formulae
\newcommand\methane{\ensuremath{\mathrm{CH_{4}}}}

\newcommand{\chemfiginput}[2][]{%
  \CatchFileDef{\chemfiginputtemp}{#2}{\csname CF_sanitizecatcode\endcsname}%
  \expandafter\chemfigdo\expandafter{\chemfiginputtemp}{#1}%
}
\newcommand{\chemfigdo}[2]{\chemfig[#2]{#1}}

\begin{document}

\begin{tabular}[]{ll}
\toprule
\textbf{Formula} & \textbf{Structure}\\
\midrule
\methane & \chemfiginput{methane} \\
\methane & \chemfiginput[chemfig style={color=red!40!black, line width=1.5pt}]{methane} \\
\methane & \chemfig{H-[:210](-[:210]H)(-[:300]H)-[:120]H} \\
\bottomrule
\end{tabular}

\end{document}

enter image description here

2
  • This one is nice and simple, easy to deploy. A few follow-up questions. Passing the option chemfig style={scale=0.5} does not seem to scale the chemfig object, how do I do this? Also, what's a nice way to vertically center the chemfig object with the text in the row?
    – John Chris
    Commented Mar 1, 2020 at 21:59
  • @JohnChris No idea for both, sorry. Open a new question.
    – egreg
    Commented Mar 1, 2020 at 22:04
3

Including \chemfig{ and } into the methane.tex instead of surrounding the \input command with it aparently seems to work:

enter image description here

\documentclass[preview,border=7pt,active,tightpage]{standalone}
\usepackage{booktabs}
\usepackage{chemfig}
\usepackage{filecontents} 
\usepackage[scaled]{helvet}
\usepackage{adjustbox}

\begin{filecontents}{methane.tex}
\chemfig{
H
    -[:210]
              (
        -[:210]H
              )
              (
        -[:300]H
              )
    -[:120]H}
\end{filecontents}


% sans serif font
\renewcommand\familydefault{\sfdefault} 

% define formulae
\def\methane{$\mathrm{CH_{4}}$}

\begin{document}
\begin{center}
\begin{tabular}[]{ll}
\toprule
\textbf{Formula} & \textbf{Structure}\\
\midrule
\methane & \adjustbox{valign=m}{\input{methane.tex}}\\ [2mm]
\bottomrule
\end{tabular}
\end{center}
\end{document}
1
  • Thanks! The final paragraph of the original question alludes to this solution. What if you wanted to scale the symbol, apply any tikz formatting? make the graphic/symbol have white lines on a dark background? I think the most elegant arrangement is not to have the \chemfig{} call in the external symbol definition.
    – John Chris
    Commented Aug 3, 2019 at 14:45
2

The tricky part about removing the \chemfig call from the external .tex files is that it changes the category codes before reading its mandatory argument. In order to cope with this, I use \CatchFileDef from the catchfile package to save the contents of methane.tex with the same category code setup as used by \chemfig.

The code below is generic and can be used with no effort for other molecules. TikZ options for molecule structure printing can be specified in a central place (\myprintmol) and there is no redundancy in the tabular: just separate the molecule names with commas:

\documentclass{article}
\usepackage{booktabs}
\usepackage{array}              % for \newcolumntype
\usepackage{collcell}           % for \collectcell
\usepackage{chemfig}
\usepackage{filecontents}
\usepackage{catchfile}          % for \CatchFileDef
\usepackage{adjustbox}          % for \adjustbox
\usepackage{etoolbox}           % for \forcsvlist

% cf. <https://tex.stackexchange.com/a/98011/73317> (Ulrike Fischer)
\DeclareMathAlphabet{\mathup}{T1}{\familydefault}{m}{n}

\newcommand*{\mydeclaremolstruct}[1]{%
  \expandafter\CatchFileDef\expandafter{\csname #1struct\endcsname}{#1.tex}%
     {\csname CF_sanitizecatcode\endcsname}%
}

\newcommand*{\myprintmol}[1]{%
 \begingroup
  % Here, you can customize how molecule structure is printed (TikZ options)
  \setchemfig{chemfig style={color=red!40!black, line width=1.5pt}}%
  %
  \adjustbox{valign=M}{% To align with vertical center of the whole molecule
    \expandafter\chemfig\expandafter{#1}% Process tokenized contents from
  }%                                    % external per-molecule .tex files
  \endgroup
}

\begin{filecontents}{methane.tex}
H
    -[:210]
              (
        -[:210]H
              )
              (
        -[:300]H
              )
    -[:120]H
\end{filecontents}

\mydeclaremolstruct{methane}    % base name of the corresponding .tex file
\newcommand*{\methane}{\mathup{CH}_{4}}

% Special column type for representing the molecule structure
\newcolumntype{M}{>{\collectcell\myprintmol}c<{\endcollectcell}}

\newcommand*{\generatetableline}[1]{%
  $\csname #1\endcsname$ & \csname #1struct\endcsname \\
}

\begin{document}

\begin{tabular}{lM}
\toprule
\textbf{Formula} & \multicolumn{1}{c}{\textbf{Structure}}\\
\midrule
\forcsvlist{\generatetableline}{methane}%
%\forcsvlist{\generatetableline}{methane, ethane, propane}%
\bottomrule
\end{tabular}

\end{document}

Screenshot

Here is the same slightly simplified, but also slightly less automatic for the table construction:

\documentclass{article}
\usepackage{booktabs}
\usepackage{array}              % for \newcolumntype
\usepackage{collcell}           % for \collectcell
\usepackage{chemfig}
\usepackage{filecontents}
\usepackage{catchfile}          % for \CatchFileDef
\usepackage{adjustbox}          % for \adjustbox

% cf. <https://tex.stackexchange.com/a/98011/73317> (Ulrike Fischer)
\DeclareMathAlphabet{\mathup}{T1}{\familydefault}{m}{n}

\newcommand*{\mydeclaremolstruct}[1]{%
  \expandafter\CatchFileDef\expandafter{\csname #1struct\endcsname}{#1.tex}%
     {\csname CF_sanitizecatcode\endcsname}%
}

\newcommand*{\myprintmol}[1]{%
 \begingroup
  % Here, you can customize how molecule structure is printed (TikZ options)
  \setchemfig{chemfig style={color=red!40!black, line width=1.5pt}}%
  %
  \adjustbox{valign=M}{% To align with vertical center of the whole molecule
    \expandafter\chemfig\expandafter{#1}% Process tokenized contents from
  }%                                    % external per-molecule .tex files
  \endgroup
}

\begin{filecontents}{methane.tex}
H
    -[:210]
              (
        -[:210]H
              )
              (
        -[:300]H
              )
    -[:120]H
\end{filecontents}

\mydeclaremolstruct{methane}    % base name of the corresponding .tex file
\newcommand*{\methane}{\mathup{CH}_{4}}

% Special column type for representing the molecule structure
\newcolumntype{M}{>{\collectcell\myprintmol}c<{\endcollectcell}}

\begin{document}

\begin{tabular}{>{$}l<{$}M}
\toprule
\textbf{Formula} & \multicolumn{1}{c}{\textbf{Structure}}\\
\midrule
\methane & \methanestruct \\
\bottomrule
\end{tabular}

\end{document}

(same output as in the previous screenshot).

2
  • I love where this solution has been taken and the functionality it suggests. For the sake of simplicity, would it make sense to subtract some of the advanced features such as: combining formula and structure and support for multiple compounds?
    – John Chris
    Commented Aug 5, 2019 at 20:22
  • 1
    My last edit added a slightly simplified solution (which is also less automatic). In this solution, each table line has to be entered like \methane & \methanestruct \\ .
    – frougon
    Commented Aug 5, 2019 at 20:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .