# how to write content of a command into a file

This question is a possible solution to question Code fails with Emergency stop, when using \expandafter\csname and such in listings, though not really an answer.

I have defined a command which may contain up to hundred lines of code including paragraph lines breaks, but basically it is just a lot of LaTeX Code. Let's assume this command is called \printhis

Now I want to export the content of \printthis into a file, which can be loaded by listings afterwards.

I have not worked before with any tex code that exports something to a file. If anyone can provide and example or link to a tutorial that would be great.

\documentclass{scrbook}

\makeatletter
\providecommand{\packagename}{templatedemo}

\RequirePackage{etoolbox}

\providecommand\demo@filename{demofile}
% #1 : package/identifier
% #2 : content
\ifcsdef{demo@content@#1}{
\expandafter\renewcommand\csname demo@content@#1\endcsname{#2}%
}{
\expandafter\newcommand\csname demo@content@#1\endcsname{#2}%
}
}

\providecommand{\demo@printhis}{}
\newcommand{\outputtofile}[1]{
\Opensolutionfile{\demo@filename}
\scantokens{\begin{Filesave}{\demo@filename}#1\end{Filesave}}
\Closesolutionfile{\demo@filename}
}

\providecommand\PrintDemo[1]{%
\ifcsdef{demo@content@#1}%
{ % print
\renewcommand{\demo@printhis}{\csuse{demo@content@#1}}
To file: \demo@printhis
\outputtofile{\demo@printhis}
}%
{ % error if not defined
}
}

\makeatother
\listfiles

\begin{document}
\PrintDemo{text}\par
From File: \IfFileExists{demofile.tex}{\input{demofile.tex}}{}
\end{document}

-
Normally you loose the line breaks. The paragraph breaks should be included as \pars, but the whole thing would be one single but very long source line. The actual writing could be done using \immediate\write\filehandle{\expandafter\unexpanded\expandafter{\printthis}}. After \newwrite\filehandle and \immediate\openout\filehandle=yourname.tex . –  Martin Scharrer Sep 23 '11 at 14:09
I want to write the code to a file, so that the listings package can read it. The code is going to contain linebreaks and empty lines. If both are lost, then the listings typesetting will be useless and therefore this apprach. –  Matthias Pospiech Sep 23 '11 at 17:15
You schould read my article in "Die TeXnische Komödie" where I described such macros for this purpose ... –  Herbert Sep 23 '11 at 17:28
@Tobi: the first issue of this year –  Herbert Sep 23 '11 at 21:32
@ Herbert: I have looked again at your article. As far as I can see, it is based on fancyvrb and its VerbatimOut environment. But is this not the same as what the answer package provides? And the principle problem - inserting the expanded version of my command is still the same. –  Matthias Pospiech Sep 25 '11 at 15:42

With some corrections your file compiles:

\documentclass{scrbook}

\RequirePackage{etoolbox}

\makeatletter

\newcommand\demo@filename{demofile}
% #1 : package/identifier
% #2 : content
\@namedef{demo@content@#1}{#2}}

\newcommand{\demo@printhis}{}
\newcommand{\outputtofile}[1]{
\Opensolutionfile{\demo@filename}
\begingroup\makeatletter
\scantokens{\begin{Filesave}{\demo@filename}#1\end{Filesave}}
\endgroup
\Closesolutionfile{\demo@filename}
}

\newcommand\PrintDemo[1]{%
\ifcsdef{demo@content@#1}%
{ % print
\letcs\demo@printhis{demo@content@#1}
To file: \demo@printhis
\expandafter\outputtofile\expandafter{\demo@printhis}
}%
{ % error if not defined
}
}

\makeatother

\begin{document}
\PrintDemo{text}\par
From File: \IfFileExists{demofile.tex}{\input{demofile.tex}}{}
\end{document}


In \AddDemo the conditional is useless, as you want to redefine the token anyway. So \@namedef (LaTeX kernel) or \csdef (etoolbox) do what's needed.

When you do \scantokens, the current category codes are applied, so the use of \demo@filename would break because @ is not a letter any more in the document. Applying \makeatletter cures the problem (but pay attention to @ characters in your examples); it can be done in a group, since we are only to write a file and the \endgroup will undo it.

However this approach has a severe limitation: line breaks cannot be preserved in the output file. That is,

\AddDemo{text}{Sample text}


and

\AddDemo{text}{%
Sample
text}


will save the same thing on the output file.

-
Thank you. Is the problem about the line breaks in the saving code or in the Filesave code? Is it possible anyhow to save code including linebreaks in a command sequence? If this is not possible I could skip the whole approach, because then I could ouput ALL example code directly within a command \printexamples. But that could be few thousand lines long... –  Matthias Pospiech Sep 25 '11 at 16:05
It works, now it is still an open question how to delete the created files automatically? –  Matthias Pospiech Sep 26 '11 at 8:46
@MatthiasPospiech TeX doesn't delete files, only create or overwrite them. Directory clean up is best done with a shell script (or Makefile); you can look at latexmk, which has many features, including clean up. –  egreg Sep 26 '11 at 8:59
The code is going to be part of a package and can not rely on external tools. –  Matthias Pospiech Oct 2 '11 at 8:47

I think the answers package might have what you're looking for. It has many commands for writing to files- in particular, you could use something like

\begin{Filesave}{myfile}
Any code you like, even paragraph skips!

\end{Filesave}


See the MWE below

\documentclass{article}

% open myfile.tex
\Opensolutionfile{myfile}

% sounds like you won't need this line
%\Newassociation{shortsolution}{shortSoln}{myfile}

\begin{document}

\section{Main body}
Here we are in the body.
\begin{Filesave}{myfile}
This will be written to the file. It can contain
linebreaks, tables, anything at all.

\begin{table}[!h]
\centering
\begin{tabular}{cc}
1   & 2
\end{tabular}
\caption{My table}
\end{table}
\end{Filesave}
\newpage

% close myfile.tex
\Closesolutionfile{myfile}

\section{Inputted file}
% input myfile.tex
\IfFileExists{myfile.tex}{\input{myfile.tex}}{}

\end{document}


EDIT

Following the comments, the printthis command can be put in the pre-amble

\newcommand{\printthis}[1]{\scantokens{\begin{Filesave}{myfile}#1\end{Filesave}}}


which can be used as follows:

\printthis{Goes to myfile

\begin{table}[!h]
\centering
\begin{tabular}{cc}
1   & 2
\end{tabular}
\caption{My other table}
\end{table}
}

-
hw wants to write the contents of a macro into a file, not the macro itself, eg: \def\foo{bar baz } should write bar baz into the file –  Herbert Sep 23 '11 at 15:11
If we find a way to insert the content into the environment, then this could be a solution. Just a remark, if this is not possible I would like to know an answer to the other question(and thus different approach) linked in the question. –  Matthias Pospiech Sep 23 '11 at 17:17
@MatthiasPospiech: see my edits, hope it is now more suitable. –  cmhughes Sep 23 '11 at 19:33
@Herbert: many thanks, see my edit –  cmhughes Sep 23 '11 at 19:47
@cmhughes: I tried your approach. A file is generated, but it only contains the command not its content. So I assume that I understood you wrong, or it still contains a principle problem. I appended this approach to the original question. Additionaly I wonder if the more simple filecontents package would be a possible solution as well? The basic problem would be the same, only answer could be exchanged by filecontents. –  Matthias Pospiech Sep 25 '11 at 15:00
show 1 more comment