如何执行 \global\renewenvironment

如何执行 \global\renewenvironment

我需要\renewenvironment在组内执行。使用\global\renewenvironment是不够的。

我需要对下面 MWE 中的宏做哪些更改\DisableMyEnvironment才能达到等效的效果\global\renewenvironment

目前,MWE 得出:

在此处输入图片描述

一旦它按预期工作,第二条蓝色线应该变成黑色。

笔记:

  • 有两个测试用例。默认的是在 a 内\foreach,注释掉的则\def\ForeachTestCase{}使用一个简单的组。

参考:

代码:

\def\ForeachTestCase{}%

\documentclass{article}
\usepackage{xcolor}
\usepackage{xstring}
\usepackage{tikz}

\newenvironment{MyEnvironment}[1][blue]{%
    \begingroup
        \color{#1}%
}{%
    \endgroup
}%

\newcommand*{\DisableMyEnvironment}{%
    %% How make this global??
    \renewenvironment{MyEnvironment}[1][]{}{}%
}%

\newcommand*{\MyTestText}[1]{%
    Some before text

    \begin{MyEnvironment}
        This should be in #1.
    \end{MyEnvironment}

    Some after text%
}

\begin{document}

\MyTestText{blue}

%\DisableMyEnvironment% <-- This works, but want it to work when used in a group as follows
\ifdefined\ForeachTestCase
    \foreach \x in {1,...,3} {%
        \IfStrEqCase{\x}{%
            {1}{}%
            {2}{\DisableMyEnvironment}%
            {3}{}%
        }%
    }
\else
    \begingroup
        \DisableMyEnvironment
    \endgroup
\fi

\medskip\par
\MyTestText{black}

\end{document}

答案1

在这里的全局范围(前言)中创建一个虚拟(或替代)环境,XEnvironment然后在\DisableMyEnvironment宏中通过以下方式全局重新分配

\global\let\MyEnvironment\XEnvironment%
\global\let\endMyEnvironment\endXEnvironment%

梅威瑟:

\documentclass{article}
\usepackage{xcolor}
\newenvironment{XEnvironment}[1][]{}{}%
\newenvironment{MyEnvironment}[1][blue]{%
    \begingroup
        \color{#1}%
}{%
    \endgroup
}%

\newcommand*{\DisableMyEnvironment}{%
    %% How make this global??
    \global\let\MyEnvironment\XEnvironment%
    \global\let\endMyEnvironment\endXEnvironment%
}%

\newcommand*{\MyTestText}[1]{%
    Some before text

    \begin{MyEnvironment}
        This should be in #1.
    \end{MyEnvironment}

    Some after text%
}

\begin{document}

\MyTestText{blue}

%\DisableMyEnvironment% <-- This works, but want it to work when used in a group as follows
\begingroup
    \DisableMyEnvironment
\endgroup

\medskip\par
\MyTestText{black}


\end{document}

在此处输入图片描述

答案2

编辑:第一种方法似乎不适用于可选参数。

编辑2:找到了一种更简单的方法\globaldefs

最终答案:

本着回答如何做到\renewenvironment全球性的精神:

\documentclass{article}
\begin{document}
  \newenvironment{test}{HELLO}{WORLD}
  \bgroup
    \globaldefs=1
    \renewenvironment{test}[1][world]{foo #1}{bar}
  \egroup
  \begin{test}[hello]
  \end{test}
\end{document}

第二个答案:

两个命令大致受\makeatletter和启发\makeatother\makerenewglobal\makerenewlocal\makerenewglobal调用时,\renewenvironment仅执行全局定义。如果\makerenewlocal调用,则执行相反的操作:使所有\renewenvironment- 定义成为本地定义。

\documentclass{article}
\makeatletter
\let\@local@newenv\@newenv
\long\def\@global@newenv#1#2#3#4{%
  \@ifundefined{#1}{\global\expandafter\let\csname#1\expandafter\endcsname\csname end#1\endcsname}{\relax}
  {\let\def\gdef\expandafter\new@command\csname #1\endcsname#2{#3}}%
  \l@ngrel@x\expandafter\gdef\csname end#1\endcsname{#4}%
}
\gdef\makerenewglobal{\global\let\@newenv\@global@newenv}
\gdef\makerenewlocal{\global\let\@newenv\@local@newenv}
\begin{document}
  \newenvironment{test}{HELLO}{WORLD}
  \bgroup\makerenewglobal
    \renewenvironment{test}[1][world]{foo #1}{bar}
  \egroup
  \begin{test}[hello]
  \end{test}
\end{document}

第一个答案:

本着半通用性的精神;一个命令,,\makeenvglobal{theenv}使环境全球化:

\documentclass{article}
\gdef\makeenvglobal#1{%
  \global\expandafter\expandafter\let\csname #1\expandafter\endcsname\csname #1\endcsname
  \global\expandafter\expandafter\let\csname end#1\expandafter\endcsname\csname end#1\endcsname
}
\begin{document}
  \newenvironment{test}{HELLO}{WORLD}
  \bgroup
    \renewenvironment{test}{foo}{bar}
    \makeenvglobal{test}
  \egroup
  \begin{test}
  \end{test}
\end{document}

印刷foo bar

答案3

按照要求 :)

我在某处读到 这里在两个组内执行\foreach命令。你可以用这个来检查这个语句(需要 e-TeX):

\documentclass{article}
\usepackage{pgffor}
\begin{document}
\foreach \i in {0}{\the\currentgrouplevel}
\end{document}

将会打印2:)

如果您想在 this 范围之外进行定义\foreach,那么您可以使用几个\aftergroups。在您的例子中,您希望\DisableMyEnvironment在两个分组级别之外运行(一个标记)。

如果您执行\aftergroup\DisableMyEnvironment,这将插入\DisableMyEnvironment到第一组之后(\aftergroup每个标记一个)。要使其达到第二级,您必须\aftergroup执行 (两个标记),因此\aftergroup\aftergroup \aftergroup\DisableMyEnvironment

请记住这不是一个全球任务,而只是局限于另一个分组级别。如果您处于第三个分组级别,则更改将在第三个分组级别结束后恢复。


就在几天前,我在做某件事(虽然我记不清是什么了——或者我能记得吗?),并且使用了非常长的\aftergroups 链,但由于缺少一个或另一个而出错。我做了什么?更长的 s 链\expandafter=D

我制作了一个(可能不是最优的)宏\afterNgroups{<N>}{<token-list>}来插入<token-list>以下<N>组:

\makeatletter
\def\afterNgroups#1#2{%
  \count@\z@
  \toks@{#2}%
  \loop
  \ifnum\count@<#1 %
    \toks2{}%
    \expandafter\@tfor\expandafter\tkn\expandafter:\expandafter=\the\toks@\do{%
      \toks2
        \expandafter\expandafter\expandafter
       {\expandafter\the\expandafter\toks\expandafter2\expandafter\aftergroup\tkn}}%
      \toks@\expandafter{\the\toks2}%
    \advance\count@\@ne
  \repeat
  \the\toks@}
\makeatother

您可以将此宏用于您的案例\afterNgroups{2}{\DisableMyEnvironment}。它显然适用于简单案例。不过,我还没有对其进行广泛测试。

相关内容