我需要\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
,那么您可以使用几个\aftergroup
s。在您的例子中,您希望\DisableMyEnvironment
在两个分组级别之外运行(一个标记)。
如果您执行\aftergroup\DisableMyEnvironment
,这将插入\DisableMyEnvironment
到第一组之后(\aftergroup
每个标记一个)。要使其达到第二级,您必须\aftergroup
执行 (两个标记),因此\aftergroup\aftergroup
\aftergroup\DisableMyEnvironment
。
请记住这不是一个全球任务,而只是局限于另一个分组级别。如果您处于第三个分组级别,则更改将在第三个分组级别结束后恢复。
就在几天前,我在做某件事(虽然我记不清是什么了——或者我能记得吗?),并且使用了非常长的\aftergroup
s 链,但由于缺少一个或另一个而出错。我做了什么?更长的 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}
。它显然适用于简单案例。不过,我还没有对其进行广泛测试。