3

In my previous question I asked about templates. I got quite a cool answer, thanks!

There is code like

\long\def\FourierIntroduction{Content}

In say the file Fourier.tex. What I would like is that if I include Fourier.tex that my template (which I made beforehand) takes these comments (if they exist) as data to produce the required document.

Hence, say I do \include{Fourier} in my main document (of course, perhaps include needs to be modified), then this document is opened and searched for commands like \FourierIntroduction and such (I would name the first part after the file itself to avoid collisions, or could this not happen?). If found, the template should execute:

\section{Introduction}
\FourierIntroduction

In such a way that I can modify the order of my template, rerun my document and get excellent result. Any suggestions how to approach this puzzle?

Edit: I have looked around on this website and have found a suggestion to use filehook by one of our moderators. I wonder if this is a good way to go:

\usepackage{filehook}
\usepackage{currfile}

\def\Introduction{Introduction}

\AtEndOfEveryFile{%
  \section{\currfilebase}%
  \subsection{Introduction}%
  \csname \currfilebase \Introduction \endcsname%
}

Edit #2: I have tried to implement "environment" and as suspected: I failed. I have the follow minimal-non-working-example:

\documentclass[11pt]{article}

\usepackage{amsmath}
\usepackage{amsthm}
\usepackage{filehook}
\usepackage{currfile}
\usepackage{environ}
\usepackage{comment}

\def\Introduction{Introduction}
\def\Methods{Methods}

\NewEnviron{introduction}{%
  \long\def{\csname \currfilebase \Introduction \endcsname}{\BODY}%
}%

\AtEndOfEveryFile{%
  \section{\currfilebase}%
  \subsection{Introduction}%
  \csname \currfilebase \Introduction \endcsname%
  \subsection{Methods}%
  \csname \currfilebase \Methods \endcsname%
}%


\begin{document}

\include{Fourier}

\end{document}

And Fourier.tex contains stuff like:

\begin{introduction}
  <TEST>
\end{introduction}

\long\def\FourierMethods{Test TWO}

I hope that the "example" is making clear what my goal is.

Edit #3: Thanks to canaaerus I now know that I should "expand". So, I should replace

\NewEnviron{introduction}{%
      \long\def{\csname \currfilebase \Introduction \endcsname}{\BODY}%
    }%

With

\NewEnviron{introduction}{%
  \expandafter\long\expandafter\xdef\csname \currfilebase \Introduction \endcsname{\BODY}%
}%

But apparently that messes up amsmath and amsthm environments. For example if I have the file Fourier.tex and I \include{Fourier} I get an error when I have this in my Fourier.tex:

\begin{introduction}
  \begin{theorem}
    Test: $f$.
  \end{theorem}
  More.
\end{introduction}

How can I fix this?

JT_NL
  • 2,153

1 Answers1

3

This looks pretty nice already. There are two things you missed. First you need to expand \csname before \def. So take \expandafter and leave away the braces. Next the new command has to be available outside the current scope and also \BODY is only knowing at define time and thus has to be expanded there. So you have to use \xdef which is short for \global\edef instead of \def. All in all this means:

\NewEnviron{introduction}{%
  \expandafter\long\expandafter\xdef\csname \currfilebase \Introduction \endcsname{\BODY}%
}%

will do what you need.

More general solution:

As the above version will make problems when \BODY is not fully expandable here is another try. It took me some effort, but I think the following will expand \BODY exactly one time and thus give you the correct result:

\NewEnviron{introduction}{%
    \expandafter\long\expandafter\xdef\csname \currfilebase \Introduction \endcsname{\expandafter\unexpanded\expandafter{\BODY}}%
}%

A bit of explanation about the expansion:

Let's assume that \BODY contains only Some \textbf{text} for simplicity, which would also trigger the problem in the first try. So now we have

\expandafter\long\expandafter\xdef\csname \currfilebase \Introduction \endcsname{\expandafter\unexpanded\expandafter{\BODY}}

The first two \expandafter make TeX step forward to the \csname-\endcsname construction and expand that, so that we get

\long\xdef{FourierIntroduction}{\expandafter\unexpanded\expandafter{\BODY}}

Now \xdef tries to expand the whole second argument and is here only inhibited by \unexpanded. Those remaining two \expandafter mean TeX jumps over \unexpanded and { to first expand \BODY (one time) and leave

\long\xdef{FourierIntroduction}{\unexpanded{Some \textbf{text}}}

So this is the point at which \xdef eats the \unexpanded and does not expand the argument of \unexpanded (the content of \BODY) any further; leaving something like

\long\global\def{FourierIntroduction}{Some \textbf{text}}
bodo
  • 6,228
  • Excellent! This works. My savior on my birthday :-). However, when I try to put some environment inside the introduction environment like something of amsthm. I get the error: ! Incomplete \iffalse; all text was ignored after line 6. Would you know what causes this? Line 6 is after the \usepackage{environ}. – JT_NL Jul 15 '12 at 09:57
  • I have added this to the original message. Thanks! :-). – JT_NL Jul 15 '12 at 10:09
  • Perfect. This works splendidly! :-). Now I should try to understand how this expansion works in TeX... Seems to be quite peculiar. – JT_NL Jul 15 '12 at 11:19