# How to use a \write command inside a \newenvironment ?

I'd like to make a new environment which would store its content in a file, so that I can read that file at another part of the document. More specifically, I want to have an environment {proof} such that its contents can be automatically moved to the appendix.

So far, I tried the following code:

\newwrite\pfs
\openout\pfs=tmp
\newenvironment{proof}{\immediate\write\pfs\bgroup}{\egroup}

\begin{proof}It's obvious.\end{proof}


However it doesn't seem to work: I get the error message File ended while scanning the text of \write. Can anybody help fix this macro?

Edit: I managed to get this macro work to work as a TeX macro:

\newwrite\pfs
\immediate\openout\pfs=tmp
\long\def\writetofile#1{\immediate\write\pfs{#1}}
\long\def\proof#1{\writetofile{\noexpand\par\noexpand\textbf{Proof:} #1}}

\proof{It's obvious.} Theorem: $0.999\ldots=1$

\immediate\closeout\pfs
\input tmp


However, I'd much prefer this macro to be converted into an environment, since most proofs will be very long...

• – egreg Nov 14 '14 at 23:24

The code below write the contents verbatim to a file. Nothing will be expanded and lines ar kept intact. The Proof environment has an optional argument for a different file name

This is especialy usefull when you write example code (see lshort) with the code on oneside and the output next to it.

\documentclass{article}
\usepackage{verbatim}
\makeatletter
\newwrite\Code@out

\newcommand\Proof{\obeylines\expandafter\ProofArg\noexpand}

\newcommand\ProofArg[1][\jobname.tmp]{%
\gdef\FName{#1}%
\begingroup
\@bsphack%
\immediate\openout\Code@out\FName%
\let\do\@makeother\dospecials%
\catcode\^^M\active%
\def\verbatim@processline{%
\immediate\write\Code@out{\the\verbatim@line}}%
\verbatim@start}

\def\endProof{%
\immediate\closeout\Code@out\@esphack
\endgroup
\input{\FName}}

\makeatother

\begin{document}
\begin{Proof}
It's obvious.
\end{Proof}

\begin{Proof}[temp]
It's also obvious $x^2$.
\end{Proof}

\end{document}

• Thanks, Danie -- after small modifications this code worked fine for me! I just had to move the \openout, \closeout and \input statements outside of macros so that all proofs get written into a single file. Although I'm still rather confused as to what the lines \let\do\@makeother\dospecials% and the next one do. – pasha Jun 17 '11 at 17:27

There are some packages for this on CTAN. E.g. answers or exam. If you want to write your own environment the easiest is probably to collect the body in a toks register or macro (e.g. with the environ package) and write it to the file at the end of the environment.

To answer the question in general: You can create your own write-to-file environment e.g. using the listings package. I'm using this in my ydoc bundle to process LaTeX code examples twice, similar to showexpl. This writes the content verbatim, while \write would expand it. This is better because you don't need to \protect fragile macros.

You need to load the listings package and also require its writefile aspect. Then you can use the write feature in an custom environment defined with \lstnewenvironment as shown below. You can also use an optional argument which is passed to a local \lstset to use other listings features, e.g. like gobble to remove a certain amount of trailing spaces.

\documentclass{article}

\makeatletter
\RequirePackage{listings}
\lst@RequireAspects{writefile}

\lstnewenvironment{proof}{%
% The content is stored in a temp box to avoid any spaces etc.
% to have an impact
\setbox\@tempboxa\hbox\bgroup
% Write file to given filename
\lst@BeginWriteFile{\jobname.prf}%
}
{%
\lst@EndWriteFile% closes output file
\egroup% End of temp box
}
\makeatother

\begin{document}

before
\begin{proof}
This is to proof the proof works!
\end{proof}
after

Later:
\input{\jobname.prf}

\end{document}


I think the filecontents package should handle that. It allows you to use the filecontents and filecontents* environments document-wide, and it allows for overwrites of existing files. With some thought, this should give you the functionality you need... I think.

Edit: Unfortunately, unless I'm missing something, this may not work in a new environment, and because of its overwrite function, you may need to assign separate files to each proof and wrap each proof in a \begin{filecontents}{<filename>} ... \end{filename} block separately. This isn't really a killer, though, since it just means you'll need to add a few more \inputs in your appendix. The documentation is here, if you'd like to give it a look.

Second edit: something like this might work for you.

\documentclass[12pt]{article}
\usepackage{filecontents,amsmath,amssymb,amsthm}

\begin{filecontents}{obviousproof.tex}
\begin{proof}It's obvious.\end{proof}
\end{filecontents}

\begin{filecontents}{anotherobvious.tex}
\begin{proof}
Let $a,b \in \mathbb{N}$ be arbitrary. Assuming that $a|b$, we can conclude that $\exists{d \in \mathbb{N}}$
such that $ad=b$. By Algebra we can deduce the following sequence of statements. If $(ad)=b$, then $(ad)c=bc$.
Therefore $(ac)d=bc$. Hence by the definition of divisibility we know that $ac|bc$.
\end{proof}
\end{filecontents}

\begin{document}
\input{obviousproof}

Given the following definition of divisibility
\begin{align*}
(\forall{a,b \in \mathbb{N}})[a | b \equiv (\exists{c \in \mathbb{N}})(ac=b)]
\end{align*}
Statement: $(\forall{a,b,c \in \mathbb{N}})[(a|b) \rightarrow (ac|bc)]$
\input{anotherobvious}
\end{document}

• @pasha In essence, this allows you to define your proofs once, then use \input{file} every time you wish to reproduce the proof. If you ever redefine the proof, you only need do so once, and the file will be updated. The \inputs will then produce your modified proof. Additionally, you need not define your proofs in the preamble as I have, you just need to define them before you call the \input`. – Jack Henahan Jun 17 '11 at 3:55
• Thank you, Jack, but your solution seems too cumbersome for my taste. I'd like to type the least, and get out of it the most. And having to keep track of potentially few dozens of files is not what I'm looking for... – pasha Jun 17 '11 at 7:17
• A fair point, and if I could think of another solution, I'd be much happier for it. If I stumble on a better solution, I'll be sure to let you know. – Jack Henahan Jun 17 '11 at 7:28