如何在 \newenvironment 中使用 \write 命令?

如何在 \newenvironment 中使用 \write 命令?

我想创建一个新环境,将其内容存储在文件中,以便我可以在文档的另一部分读取该文件。更具体地说,我希望有一个环境{proof},其内容可以自动移动到附录。

到目前为止,我尝试了以下代码:

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

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

但是它似乎不起作用:我收到错误消息File ended while scanning the text of \write。有人能帮忙修复这个宏吗?

编辑:我设法让这个宏作为 TeX 宏工作:

\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

但是,我更希望将这个宏转换成一个环境,因为大多数证明都会很长......

答案1

以下代码将内容逐字写入文件。不会展开任何内容,行保持不变。环境Proof有一个可选参数,用于不同的文件名

当您编写示例代码(参见)时这尤其有用,lshort一边是代码,另一边是输出。

\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}

答案2

CTAN 上有一些适用于此的软件包。例如answers或者exam如果你想编写自己的环境,最简单的方法可能是将主体收集到寄存器toks或宏中(例如使用environ包)并将其写入环境末尾的文件中。

答案3

总体回答这个问题:您可以创建自己的写入文件环境,例如使用包listings。我在我的ydoc包中使用它来处理 LaTeX 代码示例两次,类似于showexpl。这会逐字写入内容,而\write会对其进行扩展。这样更好,因为您不需要\protect脆弱的宏。

您需要加载listings包并需要其writefile方面。然后,您可以在如下所示定义的自定义环境中使用写入功能\lstnewenvironment。您还可以使用传递给本地的可选参数\lstset来使用其他listings功能,例如gobble删除一定数量的尾随空格。

\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
  % You can already read the file again here
}
\makeatother

\begin{document}

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

Later:
\input{\jobname.prf}

\end{document}

答案4

我认为filecontents应该可以处理这个问题。它允许您在整个文档范围内使用filecontentsfilecontents*环境,并且允许覆盖现有文件。经过一番思考,这应该可以为您提供所需的功能……我想。

编辑:不幸的是,除非我遗漏了什么,否则这可能无法在新环境中工作,并且由于其覆盖功能,您可能需要为每个证明分配单独的文件,并将每个证明\begin{filecontents}{<filename>} ... \end{filename}单独包装在一个块中。不过,这并不是什么大问题,因为这只是意味着您需要添加一些\inputs。文档是这里,如果你想看一看的话。

第二次编辑:类似这样的事情可能对你有用。

\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}

相关内容