4

i would like to seek your help on the following.

Consider the following MWE1:

\documentclass{article}
\usepackage{filecontents}
\begin{document}
Hi
\begin{filecontents*}{dummy.tex}
some text and math here $A=s^2$
\end{filecontents*}
\end{document}

It works fine. An external file "dummy.tex" is created with the contents "some text and math here $A=s^2$".

Now, consider the following MWE2:

\documentclass{article}
\usepackage{filecontents}
\newcommand*{\somecommand}{some text and math here $A=s^2$}%
\begin{document}
Hi
\begin{filecontents*}{dummy.tex}
\somecommand
\end{filecontents*}
\end{document}

An external file "dummy.tex" is also created, but with the contents "\somecommand". What I would want instead is for the file to contain "some text and math here $A=s^2$".

Now, consider the following MWE3:

\documentclass{article}
\usepackage{ifthen}
\usepackage{filecontents}
\newcommand*{\somecommandA}{some text and math here $A=s^2$}%
\newcommand*{\somecommandB}{5}%
\begin{document}
Hi
\begin{filecontents*}{dummy.tex}
\somecommandA
\\
\ifthenelse{\equal{\somecommandB}{5}}{5}{4}
\end{filecontents*}
\end{document}

An external file "dummy.tex" is also created, but with the contents

\somecommandA
\\
\ifthenelse{\equal{\somecommandB}{5}}{5}{4}

What I would want instead is for the file to contain

some text and math here $A=s^2$
5

Is there a way we can put commands and macros inside the filecontents* environment, and have the external file contain the expanded commands and macros? (I understand filecontents* behave like verbatim.) If not filecontents*, is there another package/environment that can achieve this?

Kindly seeking your help. Thank you.

2
  • As you diagnosed yourself, filecontents reads things verbatim, so \command and zcommand are pretty much the same. It can be changed to make MWE2 work because \somecommand is a simple macro that expands to text. MWE3 is probably not possible (with a reasonable amount of effort, at least) because \ifthenelse does not “simply expand” to text. Mar 24, 2020 at 19:49
  • thank you for the insight, @PhelypeOleinik Mar 24, 2020 at 19:56

1 Answer 1

6

As you diagnosed yourself, filecontents reads things verbatim, so \command and zcommand are pretty much the same.

With a few changes, it can be changed to make MWE2 work because \somecommand is a simple macro that expands to text. For example, here's a \filecontentsspecials<esc><bgroup><egroup> macro, which makes the next filecontents environment use the character <esc> as escape character (usually \), <bgroup> as begin- and <egroup> as end-group characters (usually { and } respectively). Important: \filecontentsspecials\\\{\} will not work. The chosen characters cannot be any of \\\{\}. |[], for example are valid.

After you use \filecontentsspecials, the next (and only the next) filecontents will carry out fill expansion of its contents, expanding macros. Things not to be expanded should be prefixed with |noexpand or wrapped in |unexpanded[...]. Here's the code:

\def\filecontentsspecials#1#2#3{
  \global\let\ltxspecials\dospecials
  \gdef\dospecials{\ltxspecials
    \catcode`#1=0
    \catcode`#2=1
    \catcode`#3=2
    \global\let\dospecials\ltxspecials
  }
}

\documentclass{article}
\newcommand*{\somecommand}{some text and math here $A=s^2$}%
\begin{document}
Hi
\filecontentsspecials|[]
\begin{filecontents*}[overwrite]{dummy.tex}
|somecommand % this expands
\somecommand % this does not
\end{filecontents*}
\end{document}

and the file will contain:

some text and math here $A=s^2$ % this expands
\somecommand % this does not

MWE3 is not possible (with a reasonable amount of effort, at least) because \ifthenelse does not “simply expand” to text.

8
  • hi @PhelypeOleinik. thank you for your response. for some reason (maybe my OS or my version of MikTeK), your MWE as is did not compile. thus, I modified your MWE a little bit. I included \usepackage{filecontents} after \documentclass{article}, and I removed the [overwrite] option, and your MWE compiled. thank you. I'm still hoping, though, that I can put \ifthenelse and \renewcommand macros inside the filecontents* environment. the program I am making will need these macros expanding inside the filecontents* environment. Mar 25, 2020 at 4:19
  • 1
    @beethovengg14 The [overwrite] option was introduced to filecontents in 19-10-01 (see: tex.stackexchange.com/a/511507/134574), so you'd need to update. But the modifications you made were correct. Now about \renewcommand: it won't work because the result of the command doesn't translate to simple text to be written (it does assignments, so it changes the state of TeX's memory), which means it doesn't “expand”, it “executes”. You won't be able to simply expand \renewcommand (or \ifthenelse, or many other macros) into text to be written because they are not expandable. Mar 25, 2020 at 11:51
  • 1
    @beethovengg14 (cont'd) You have three options: 1) Find another way around: depending on what you want to do you don't need to expand \renewcommand (it's quite unlikely, actually). 2) For the specific case of \ifthenelse with integers you can use \ifnum\somecommandB=5 5\else 4\fi (for other data types there are other better (and expandable) conditionals). 3) If you absolutely need to expand \renewcommand you need to emulate TeX in TeX; there is one package, unravel, which does this, and it's 6000 lines of code, so you might want to reconsider 1 and 2. What is your aim? Mar 25, 2020 at 11:54
  • 1
    @beethovengg14 Glad it helped :-) Note that the filecontents update I mentioned was introduced in the LaTeX kernel, so you have to update LaTeX itself, not only the filecontents package (if you use MiKTeX, you have to update the latex-base package, and if you use TeXLive 2019 or greater, doing tlmgr update --all should suffice) Apr 1, 2020 at 1:23
  • 1
    @FaheemMitha Sorry for the delay. I change the definition of \dospecials to make the three characters (in the example |, [ and ]) mean the same as \, { and } by changing their catcode to 0, 1 and 2, then revert back the original definition of \dospecials. \filecontentsspecials is just a thin wrapper around that. The catcode manipulation is because the varbatim-isation of filecontents makes the backslash be an ordinary character; thus you need something else. Nov 29, 2021 at 22:12

You must log in to answer this question.

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