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?

2 Answers 2

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}
3
  • 1
    I don't think the problem is due to \foreach, otherwise a single \noexpand wouldn't work, because \write expands its argument.
    – egreg
    Commented Oct 22, 2013 at 8:17
  • @egreg Hmm, probably you are right. I'll edit
    – Joseph Wright
    Commented Oct 22, 2013 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
    Commented Oct 22, 2013 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}"}}

You must log in to answer this question.

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