# Writing environments out to files and prepending/appending additional code

I am using the following code snippet to write environments out to files and run arbitrary commands (like python or Rscript). It works quite nice however I would like to write something to the file before and after I insert the stuff from the enviroment there:

\documentclass{beamer}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

\usepackage{fancyvrb}
\makeatletter

\newenvironment{Rtest}[1]%
{\xdef\d@tn@me{#1}%
% \xdef\r@ncmd{Rscript #1.R > #1.Rlog}% uncomment to run command on file
\typeout{Writing file #1}\VerbatimOut{#1.R}%
}
{\endVerbatimOut %
\toks0{\immediate\write18}%
%\expandafter\toks\expandafter1\expandafter{\r@ncmd}% uncomment to run command on file
%\edef\d@r@ncmd{\the\toks0{\the\toks1}}\d@r@ncmd % uncomment to run command on file
\input{\d@tn@me.R}%
}

\makeatother

\begin{document}

\frame[containsverbatim]{

\begin{Rtest}{hello}
Hallo Welt
\end{Rtest}

}

\end{document}


What I would like to achieve is to have an environment like the following:

\begin{Rtest}{hello}{beforecode}{aftercode}
Hallo Welt
\end{Rtest}


that results in hello.R looking like this:

beforecode
Hallo Welt
aftercode


How can I modify the code above to accomplish this?

• Not an answer to the question; but \immediate\write18{\r@ncmd} is much easier than that long series of commands: \r@ncmd has been defined by \xdef, so it has survived full expansion so it can go as argument to \write. – egreg Dec 30 '14 at 11:01
• Use \begin{frame}[fragile]...\end{frame} and not \frame{...}. – egreg Dec 30 '14 at 11:38

This solution is based on this answer of Ulrike Fischer.

\documentclass{beamer}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

\usepackage{environ}

\newwrite\myexport

\makeatletter
\NewEnviron{Rtest}[3]{%
\immediate\openout\myexport=#1.R%
\toks@={#2}%
\immediate\write\myexport{\the\toks@}%
\toks@=\expandafter{\BODY}%
\immediate\write\myexport{\the\toks@}%
\toks@={#3}%
\immediate\write\myexport{\the\toks@}%
\immediate\closeout\myexport%
\input{#1.R}
}
\makeatother

\begin{document}

\frame[containsverbatim]{

\begin{Rtest}{hello}{beforecode}{aftercode}
Hallo Welt
\end{Rtest}

}

\end{document}


Contents of hello.R

beforecode
Hallo Welt
aftercode


Output

• This will tokenize the contents of Rtest, losing the possibility of doing verbatim; for instance, line breaks will be lost. – egreg Dec 30 '14 at 11:36
• @egreg I know, but I'm not sure about what has to be the contents of the .R file and anyway, I can't do any better... – karlkoeller Dec 30 '14 at 11:37
• Rtest will contain arbitrary R or Python code, line breaks must remain as they are as they may have a special meaning. – Uwe Ziegenhagen Dec 30 '14 at 12:20

Customizing fancyvrb's VerbatimOut might be the simplest approach. This should give you a good starting point for additional customization.

I wrote this for Python since I don't have an R installation handy. The test environment takes the base name of the script, the before code, and the after code, in addition to an optional argument that specifies whether the code is executed. If code is executed, the output is brought in verbatim. You should be able to customize this easily to get whatever you need.

This assumes that the before code and after code are single lines.

\documentclass{beamer}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

\usepackage{fancyvrb}
\usepackage{upquote}
\usepackage{etoolbox}
\makeatletter
\def\VerbatimOutPlus{\FV@Environment{}{VerbatimOutPlus}}

% Write #2 before and #3 after environment contents
\def\FVB@VerbatimOutPlus#1#2#3{%
\@bsphack
\begingroup
\FV@UseKeyValues
\FV@DefineWhiteSpace
\def\FV@Space{\space}%
\def\FV@ProcessLine{\immediate\write\FV@OutFile}%
\immediate\openout\FV@OutFile #1\relax
\immediate\write\FV@OutFile{#2}%
\def\FV@appendline{#3}%
\let\FV@FontScanPrep\relax
\let\@noligs\relax
\FV@Scan}

\def\FVE@VerbatimOutPlus{%
\immediate\write\FV@OutFile{\FV@appendline}%
\immediate\closeout\FV@OutFile\endgroup\@esphack}

\DefineVerbatimEnvironment{VerbatimOutPlus}{VerbatimOutPlus}{}

\newenvironment{PYtest}[4][]%
{\VerbatimEnvironment
\def\FV@run@opts{#1}%
\def\FV@Plus@outfilename{#2.py}%
\begin{VerbatimOutPlus}{#2.py}{#3}{#4}}%
{\end{VerbatimOutPlus}%
\VerbatimInput{\FV@Plus@outfilename}%
\ifdefstring{\FV@run@opts}{run}{%
\hrule
\immediate\write18{python \FV@Plus@outfilename\space> \FV@Plus@outfilename log}%
\VerbatimInput{\FV@Plus@outfilename log}}{}}
\makeatother

\begin{document}

\begin{frame}[fragile=singleslide]
\begin{PYtest}[run]{hello}{'''beforecode'''}{'''aftercode'''}
print('Text')
\end{PYtest}
\end{frame}

\end{document}


• I am receiving an error message with your code: ! I can't write on file hello.py'.` – Uwe Ziegenhagen Jan 1 '15 at 5:26
• @UweZiegenhagen That looks like a permissions issue. Probably the same as this question if you are on Windows. – G. Poore Jan 1 '15 at 16:08