我正在使用以下代码片段将环境写入文件并运行任意命令(如python
或Rscript
)。 它工作得很好,但是我想在将环境中的内容插入到文件之前和之后向文件中写入一些内容:
\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@[email protected]}%
}
\makeatother
\begin{document}
\frame[containsverbatim]{
\begin{Rtest}{hello}
Hallo Welt
\end{Rtest}
}
\end{document}
我想要实现的是拥有如下的环境:
\begin{Rtest}{hello}{beforecode}{aftercode}
Hallo Welt
\end{Rtest}
结果hello.R
如下:
beforecode
Hallo Welt
aftercode
我该如何修改上面的代码来实现这一点?
答案1
此解决方案基于此回答乌尔里克·菲舍尔 (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}
内容hello.R
beforecode
Hallo Welt
aftercode
输出
答案2
自定义fancyvrb
可能VerbatimOut
是最简单的方法。这应该为您提供了进行其他自定义的良好起点。
由于手边没有 R 安装,因此我使用 Python 编写了此代码。测试环境采用脚本的基本名称、之前的代码和之后的代码,以及指定是否执行代码的可选参数。如果执行了代码,则输出将逐字逐句地呈现。您应该能够轻松自定义它以获得所需的任何内容。
这假设之前的代码和之后的代码都是单行。
\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}%
\FV@DefineTabOut
\def\FV@ProcessLine{\immediate\write\FV@OutFile}%
\immediate\openout\FV@OutFile #1\relax
% Added next 2 lines
\immediate\write\FV@OutFile{#2}%
\def\FV@appendline{#3}%
\let\FV@FontScanPrep\relax
\let\@noligs\relax
\FV@Scan}
\def\FVE@VerbatimOutPlus{%
% Added next line
\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}