6

My objective is to automatically compile parameterized template from within a main input file. For each compilation, a unique jobname and parameter are passed to the compiler. The problem is, passing parameter requires me to manage both expansion and unexpansion in the proper order.

Consider the important part of MWE,

\immediate\write18{pdflatex -jobname=\outputfilename\space "\def\name{\target} \input{template}"}

The \target must be expanded while \def\name must be unexpanded.

\documentclass[preview,border=12pt]{standalone}
\usepackage{filecontents}
\begin{filecontents*}{template.tex}
\documentclass[preview,border=12pt]{standalone}
\begin{document}
Hello \name
\end{document}
\end{filecontents*}

\usepackage{pgffor,graphicx}
\foreach \outputfilename/\target in {a/Andy,b/Bill,c/Charlie}{\immediate\write18{pdflatex -jobname=\outputfilename\space "\def\name{\target} \input{template}"}}
\begin{document}
The files we created automatically are:

\foreach \outputfilename in {a,b,c}{\fbox{\includegraphics[scale=2]{\outputfilename}}\endgraf}
\end{document}

I have not learnt the token expansion so this case seems very disturbing in my daily usage of TeX. How to manage these expansions?

10

The \write operation performs expansion, which is similar to \edef. As such, you need \noexpand to protect any tokens that need to be 'left alone'. You have:

  • \outputfilename
  • \target
  • \space

to be expanded and

  • \def
  • \name
  • \input

to be left alone. Of those, \def is a non-expandable primitive in any case, so all you need is two \noexpands:

\documentclass[preview,border=12pt]{standalone}
\usepackage{filecontents}
\begin{filecontents*}{template.tex}
\documentclass[preview,border=12pt]{standalone}
\begin{document}
Hello \name
\end{document}
\end{filecontents*}

\usepackage{pgffor,graphicx}
\foreach \outputfilename/\target in {a/Andy,b/Bill,c/Charlie}
  {\immediate\write18{pdflatex -jobname=\outputfilename\space
    "\def\noexpand\name{\target} \noexpand\input{template}"}}
\begin{document}
The files we created automatically are:

\foreach \outputfilename in {a,b,c}{\fbox{\includegraphics[scale=2]{\outputfilename}}\endgraf}
\end{document}
  • 1
    I don't think the problem is due to \foreach, otherwise a single \noexpand wouldn't work, because \write expands its argument. – egreg Oct 22 '13 at 8:17
  • @egreg Hmm, probably you are right. I'll edit – Joseph Wright Oct 22 '13 at 8:21
  • I didn't go deeply into pgffor.code.tex, but if I do \foreach\i in {a,b,c}{\show\i} the first answer is > \i=macro:, which proves that \i is not expanded. – egreg Oct 22 '13 at 8:27
3
\foreach \outputfilename/\target in {a/Andy,b/Bill,c/Charlie}{%
  \immediate\write18{pdflatex -jobname=\outputfilename\space 
     "\def \string\name {\target} \string\input{template}"}}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.