Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

How can one write the body of an environment verbatim to an external file. I tried the following but get problems if the body contains undefined macros (error) or e.g. a % (disappears in the output).

Try 1
Using environ to get the environment content.

\ProvidesPackage{tofile1}

\RequirePackage{environ}

% counter for external files
\newcounter{TF@File}

\newwrite\TF@out

\NewEnviron{tofile}{%
    \stepcounter{TF@File}
    \edef\TF@outFile{ext-\jobname-\theTF@File.tex}
    \typeout{Name: \TF@outFile}
    \immediate\openout\TF@out=\TF@outFile
    \typeout{\TF@outFile\space opened}
    \immediate\write\TF@out{\BODY}
    \typeout{\TF@outFile\space written}
    \immediate\closeout\TF@out
    \typeout{\TF@outFile\space closed}
}

% test.tex
\documentclass{article}

\usepackage{tofile1}

\begin{document}
Test

\begin{tofile}
That's {a short Test}
which works
but ignores line breaks
\end{tofile}

Text

\begin{tofile}
\xx That's {another Test}%
This one doesn't work ...
it gives an error because \xx is undefined
\end{tofile}
\end{document}

This one creates the two desired files ext-test-1.tex and ext-test-1.tex but linebreaks are ignored and an undefined control sequence (\xx) causes an error. Furthermore the percent char is interpreted as comment not as simple character. I guess come catcode magic could help.

Try 2
Using the filecontents package.

\ProvidesPackage{tofile2}

\RequirePackage{environ}
\RequirePackage{filecontents}

% counter for external files
\newcounter{TF@File}

\newwrite\TF@out

\newenvironment{tofile}{%
    \stepcounter{TF@File}
    \edef\TF@outFile{ext-\jobname-\theTF@File.tex}
    \begin{filecontents}{\TF@outFile}
}{
    \end{filecontents}
}

Same test file as above ...

This one creates only the first file ext-test-1.tex and the an error occurs because the end of filecontens can’t be determined correctly.

Is there another way do do this, maybe a package?

share|improve this question
    
The reason why the filecontents solutions doesn't work is that it looks for \end{filecontents} verbatim and can't find it inside \end{tofile}. In general you can't include verbatim macros or environments in other macros or environments. –  Martin Scharrer Dec 10 '11 at 11:43
    
@MartinScharrer: Yea, I thought so … –  Tobi Dec 10 '11 at 14:58
    
have a look at the answers package too –  cmhughes Dec 10 '11 at 16:14
    
About writing % into a file see also tex.stackexchange.com/q/34390/6865 –  Stephen Dec 10 '11 at 17:13

2 Answers 2

up vote 13 down vote accepted

You can look at the definition of verbatimwrite in verbatim.sty or use the facilities provided by the fancyvrb package:

\documentclass{article}

\usepackage{fancyvrb}
\newenvironment{tobiwrite}[1]
  {\typeout{Writing file #1}\VerbatimOut{#1}}
  {\endVerbatimOut}

\begin{document}
\begin{tobiwrite}{tobi.txt}
a

b
c
\end{tobiwrite}
\end{document}

Instead of \typeout you can do whatever you want (for example, checking whether the file already exists with \IfFileExists).

share|improve this answer
    
@MartinScharrer, egreg: Thank you both seems like both answers math my questions. Could you pleas figure out the differences if there are any? –  Tobi Dec 10 '11 at 14:59
    
@Tobi A very late answer, but it seems I missed seeing your comment. What are the differences? Well, listings loads fancyvrb, first of all. However, the definition of \lst@BeginWriteFile is different from \VerbatimOut, since many more settings are necessary for supporting the full power of listings. If you're only interested in verbatim copy, \VerbatimOut is more efficient. –  egreg Feb 2 '13 at 16:28
    
Thank you :-) ... –  Tobi Feb 2 '13 at 16:56

It is possible to use internal macros from the listings package to do this.

\documentclass{article}

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

\lstnewenvironment{yourenv}{%
  % some code before
  % including \lstset{..}
  % Write file to given filename
  \lst@BeginWriteFile{\jobname.txt}%
}
{%
  \lst@EndWriteFile% closes output file
}
\makeatother

\begin{document}
% ...    
\end{document}

Compare with the similar code I provided in my answers to the following questions:
LaTeX documentation with verbatim environment
How to use a \write command inside a \newenvironment ?

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.