1

I'm posting this in case it's useful to anyone; it's not actually a question.

Commands defined inside environments like enumerate are automatically fragile, and are lost outside the environment. This is frequently inconvenient. However, one can make the definitions global. In my earlier question How to make a command to automate the processing of a list of commands, that @Skillmon solved for me, I wanted to know how to automate the make-it-global process for a specified list of (already defined) command names. It's trickier than you might think.

Although this is a neat solution, if you do a lot of this in a large document, you have to be sure all your global definitions have different names.

If however, when you later need your commands outside their defining environment, they are only needed in a localised part of your document, it may make more sense to store those definitions in a file, and re-import them when you need them. That way, different definition sets don't have to be given mutually exclusive sets of names. As before, automating this is tricky. Here's an example that works. It includes improvements due to comments by @Skillmon, @egreg and @David Carlisle below.

\documentclass{article}
\usepackage{fp}
\usepackage{ifthen}
\usepackage{etoolbox}

\makeatletter % These "\makeat"s must be outside the newcommand
\newwrite\defsout
\newcommand{\WriteDefsToFile}[2]{%
  \immediate\openout\defsout=#1_defs.tex
  \@for\cs:={\unexpanded{#2}}\do{%
    \immediate\write\defsout{%
      \def\expandafter\unexpanded\expandafter{\cs}{\cs}%
    }%
  }%
  \immediate\write\defsout{\unexpanded{ }}%
  \immediate\closeout\defsout
}
\makeatother

\begin{document}

\def\RandSeed{\the\year}

Start an enumerate.

\begin{enumerate}

\item   

Define some commands related to what this item's about.
\FPeval{\RnSd}{clip(\RandSeed*9876)} % It's not important what coomands are being defined
\FPseed\RnSd
\FPrandom{\rndA}
\FPrandom{\rndB}
\FPrandom{\rndC}
\FPeval{\uu}{trunc(11*\rndA, 0)}
\FPeval{\vv}{trunc(- 30 - 61*\rndB, 0)}
\FPeval{\ww}{trunc(101*\rndC + 100, 0)}

Some of the text involves these commands: \uu, \vv\ \& \ww.

\WriteDefsToFile{UVW}{\uu,\vv,\ww}

\end{enumerate}

%%% Following would give and "Undefined control sequence" error
%More text involving \uu, \vv\ \& \ww.

\input{UVW_defs}

After the enumerate, there's more text involving these commands: \uu, \vv\ \& \ww.

\end{document}
  • I'd put \newwrite outside of the command. – Skillmon Jan 29 '18 at 6:49
  • @Skillmon. Thanks. But why? Is it more robust, or more efficient, or just neater? – cwhctza Jan 29 '18 at 6:54
  • @cwhctza Try calling \WriteDefsToFile sixteen times. Since you're allocating a new output stream per call, you'll exhaust the supply. This is where using \newwrite outside the definition of \WriteDefsToFile is important. – egreg Jan 29 '18 at 7:39
  • 1
    This is a question and answers site. You should ask a question that can be answered (by yourself, for instance). – egreg Jan 29 '18 at 7:42
  • as well as the misplaced \newwrite you are missing % at the ends of lines so the command will insert spaces into the document at the point you do the write (which may or may not affect the typesetting depending where you do that) – David Carlisle Jan 29 '18 at 8:03

Your Answer

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

Browse other questions tagged or ask your own question.