为什么我的环境还没有恢复?

为什么我的环境还没有恢复?

我不知道为什么,但我试着跟随https://tex.stackexchange.com/a/286089/116348重新定义如下环境:

\let\answers\questions
\let\endanswers\endquestions

以拯救和恢复环境。

我尝试过这样做:

\documentclass[]{article}

\begin{document}

\NewDocumentEnvironment{mydummyenv}{m}{I will print #1 before. ``}{'' And I will print #1 after.}

\begin{mydummyenv}{MyArg}
  Hey
\end{mydummyenv}

%%% Overwrite the env and store the old version
\let\mydummyenvOrig\mydummyenv
\let\endmydummyenvOrig\endmydummyenv
\DeclareDocumentEnvironment{mydummyenv}{D<>{}}{
  I replace the dummy environment, see my value #1.
}{}

%% Restore the env
\let\mydummyenv\mydummyenvOrig
\let\endmydummyenv\endmydummyenvOrig

\begin{mydummyenv}{MyArg}
  Hey
\end{mydummyenv}

\end{document}

但遗憾的是使用的是旧环境:

在此处输入图片描述

您是否有解决方案来保存并稍后恢复任意环境?理想情况下,此解决方案应仅取决于环境的名称(我不想对原始参数的提出方式做任何假设,因为我只知道新环境的定义)。

附言:实际上,我的问题更加复杂,因为它是我的强大外部化库的一部分并且涉及重新扫描......所以仅将重新定义的环境包装在一个组中作为一种解决方法对于我的实际问题不起作用。

答案1

您应该使用\NewEnvironmentCopy\DeclareEnvironmentCopy而不是\let来保存和恢复环境定义。这样,您就不需要知道环境最初是如何定义的(使用\NewDocumentEnvironment\newenvironment),一切应该都能正常工作™。

\documentclass[]{article}

\begin{document}

\NewDocumentEnvironment{mydummyenv}{m}{I will print #1 before. ``}{'' And I will print #1 after.}

\begin{mydummyenv}{MyArg}
  Hey
\end{mydummyenv}

%%% Overwrite the env and store the old version
\NewEnvironmentCopy{mydummyenvOrig}{mydummyenv}
\DeclareDocumentEnvironment{mydummyenv}{D<>{}}{
  I replace the dummy environment, see my value #1.
}{}

%% Restore the env
\DeclareEnvironmentCopy{mydummyenv}{mydummyenvOrig}

\begin{mydummyenv}{MyArg}
  Hey
\end{mydummyenv}

\end{document}

答案2

Skillmon 已经解释了如何修复,这就是您的代码无法工作的原因。

一般来说\NewDocumentEnvironment{foo}仍然定义\foo\endfoo,但这些只是表面宏。

事实上你可以尝试

\NewDocumentEnvironment{foo}{}{x}{y}
\show\foo
\show\endfoo
\stop

你会得到

> \foo=\protected macro:
->\__cmd_start_env:nnnnn {}{foo}{}{}{}.
l.2 \show\foo

?
> \endfoo=macro:
->\environment foo end aux .
l.3 \show\endfoo

?

其中\environment␣foo␣end␣aux␣(csname 中有四个空格)是包含“结束部分”的单个宏。“开始部分”的真正代码是隐藏的。

\let\fooOrig\foo只需保存表面宏。但是当您这样做\RenewDocumentCommand{foo}(使用适当的参数)时,表面命令根本不会改变,只有内部实际代码会改变。如果您稍后这样做

\let\foo\fooOrig

你做没有什么。内部实际代码仍然是重新定义的代码,这解释了您的问题。

因为\newenvironment当环境采用可选参数时,问题会是相同的。在较新版本的 LaTeX 之前,您必须使用\LetLtxMacro才能安全保存,但这不适用于使用 定义的环境\NewDocumentEnvironment

我不建议通过重新定义环境(或命令)来回切换,因为你不知道foo在给定点会做什么。但你可以按照所示操作,或者更好的做法是,

\NewDocumentEnvironment{foo}{...}{...}{...}
\NewEnvironmentCopy{fooOrig}{foo}

\RenewDocumentEnvironment{foo}{...}{...}{...}

\RenewEnvironmentCopy{foo}{fooOrig}

答案3

这演示了两个不同名称的用法。我遵循“\def一次,\let反复”的规则。

\documentclass[]{article}

\NewDocumentEnvironment{mydummyenv}{m}{I will print #1 before. ``}{'' And I will print #1 after.}

\NewDocumentEnvironment{anothername}{D<>{}}{
  I replace the dummy environment, see my value #1.
}{}

\begin{document}

\begin{mydummyenv}{MyArg}
  Hey
\end{mydummyenv}

%%% Overwrite the env and store the old version
\let\mydummyenvOrig\mydummyenv
\let\endmydummyenvOrig\endmydummyenv

\let\mydummyenv\anothername
\let\endmydummyenv\endanothername

\begin{mydummyenv}{MyArg}
  Hey
\end{mydummyenv}

%% Restore the env
\let\mydummyenv\mydummyenvOrig
\let\endmydummyenv\endmydummyenvOrig

\begin{mydummyenv}{MyArg}
  Hey
\end{mydummyenv}

\end{document}

相关内容