我想定义一个在嵌套时行为不同的环境。此环境应忽略环境开头和结尾的空格。当它不嵌套时,我可以按我的意愿工作。但是,当它嵌套时,我似乎无法获得所需的行为。
这里的第一个框是使用非嵌套版本所需的行为。我希望此环境的第二个嵌套版本表现得好像它不是嵌套的。但是,当前实现存在两个问题:
- 嵌套时,我需要添加尾随
%
。\begin{MyBoxedEnvironment}%
否则,中间会多出一行。(参见1
在 MWE 中)。 - 嵌套时,我不能在此环境的开头后面留空行。可以通过手动添加来解决这个问题
\par\noindent
,但我更愿意不必这样做。(参见2
在 MWE 中)。
如下所示,我使用计数器来计算嵌套的深度,并且只有\begin
当计数器为零时才\end
计算环境mdframed
。如果有更好的方法来检测环境是否嵌套,那也会很有用。
代码:
\documentclass{article}
\usepackage{xcolor}
\usepackage{mdframed}
\newcommand*{\Text}{%
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Sed accumsan nulla ac ipsum elementum interdum.
Praesent ultricies faucibus turpis, non scelerisque nisi bibendum et.
}%
\newmdenv[%
backgroundcolor=yellow!10,%
linewidth=2pt,%
skipabove=0pt,%
skipbelow=0pt,%
]{MyBoxedEnvironmentMdframed}%
\newcounter{MyBoxEnvironmentDepth}%
\setcounter{MyBoxEnvironmentDepth}{0}% just to be clear we start at 0
\newenvironment{MyBoxedEnvironment}{%
\ignorespaces%
\par\noindent%
\ifnum\value{MyBoxEnvironmentDepth}>0%
% Ignore begin environment since it is nested.
\else%
\begin{MyBoxedEnvironmentMdframed}%
\fi%
\addtocounter{MyBoxEnvironmentDepth}{1}% increment depth
}{%
\addtocounter{MyBoxEnvironmentDepth}{-1}% decrement depth
\ifnum\value{MyBoxEnvironmentDepth}>0%
% Ignore end environment since it is nested.
\else%
\end{MyBoxedEnvironmentMdframed}%
\fi%
\ignorespacesafterend%
}%
\begin{document}
\begin{MyBoxedEnvironment}
\Text
\par\noindent
\textcolor{red}{\Text}
\end{MyBoxedEnvironment}
\begin{MyBoxedEnvironment}
\Text
\begin{MyBoxedEnvironment} % 1. Why space here matter?
% 2. Why does blank line above yield extra line
%\par\noindent% Don't want to have to add this
\textcolor{red}{\Text}
\end{MyBoxedEnvironment}
\end{MyBoxedEnvironment}
\end{document}
答案1
看来你实际上并不需要计数器,只需要一个开关如果你定义 \foo 来执行,\begin{MyBoxedEnvironmentMdframed}
那么您的环境可以调用\foo\let\foo\relax
,并且对于最终环境也是如此,那么在嵌套情况下\foo
将不执行任何操作,而不需要计数器或显式测试。
根据要求更新的示例
\documentclass{article}
\usepackage{xcolor}
\usepackage{mdframed}
\newcommand*{\Text}{%
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Sed accumsan nulla ac ipsum elementum interdum.
Praesent ultricies faucibus turpis, non scelerisque nisi bibendum et.%
}
\newmdenv[
backgroundcolor=yellow!10,
linewidth=2pt,
skipabove=0pt,
skipbelow=0pt,
]{MyBoxedEnvironmentMdframed}
\newenvironment{MyBoxedEnvironment}{%
\def\MyBoxedEnvironment{%
\let\endMyBoxedEnvironment\empty
\par\noindent\ignorespaces}
\begin{MyBoxedEnvironmentMdframed}%
\par\noindent\ignorespaces
}{%
\end{MyBoxedEnvironmentMdframed}%
\ignorespacesafterend
}
\begin{document}
\begin{MyBoxedEnvironment}
\Text
\par\noindent
\textcolor{red}{\Text}
\end{MyBoxedEnvironment}
\begin{MyBoxedEnvironment}
\Text
\begin{MyBoxedEnvironment}
\textcolor{red}{\Text}
\end{MyBoxedEnvironment}
\end{MyBoxedEnvironment}
\end{document}
编辑:附加评论(对于评论系统来说显然太长了)
在这里使用\relax
可能足够安全,但它会将不可扩展的标记放入流中,而空格/换行符则不会,因此这样做并不总是安全的。\ignorespaces
只忽略其后的空格标记,因此如果您在它后面跟上一些不可扩展的标记(如在 MWE 中),它什么也不做。同样,在您完成后,\par
空白行将完全不起作用。除非您确定只想要文本,否则通常不建议以此开头,因为\noindent
这实际上是段落的开始,因此嵌套的显示材料将被错误设置。\parindent
如果您只想要非缩进的段落,最好将其设置为零。
答案2
两个错误:\ignorespaces
必须放在最后,在 之后\par\noindent
;嵌套环境中的缩进当然是由 之后的空行引起的\begin{MyBoxedEnvironment}
。
以下是正确放置字符的更正版本%
(例如,0
在\ifnum
后应该有不是是%
)。
\documentclass{article}
\usepackage{xcolor}
\usepackage{mdframed}
\newcommand*{\Text}{%
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Sed accumsan nulla ac ipsum elementum interdum.
Praesent ultricies faucibus turpis, non scelerisque nisi bibendum et.%
}
\newmdenv[
backgroundcolor=yellow!10,
linewidth=2pt,
skipabove=0pt,
skipbelow=0pt,
]{MyBoxedEnvironmentMdframed}
\newcounter{MyBoxEnvironmentDepth}
\setcounter{MyBoxEnvironmentDepth}{0}% just to be clear we start at 0
\newenvironment{MyBoxedEnvironment}{%
\ifnum\value{MyBoxEnvironmentDepth}>0
% Ignore begin environment since it is nested.
\else
\begin{MyBoxedEnvironmentMdframed}%
\fi
\addtocounter{MyBoxEnvironmentDepth}{1}% increment depth
\par\noindent\ignorespaces
}{%
\addtocounter{MyBoxEnvironmentDepth}{-1}% decrement depth
\ifnum\value{MyBoxEnvironmentDepth}>0
% Ignore end environment since it is nested.
\else
\end{MyBoxedEnvironmentMdframed}%
\fi
\ignorespacesafterend
}
\begin{document}
\begin{MyBoxedEnvironment}
\Text
\par\noindent
\textcolor{red}{\Text}
\end{MyBoxedEnvironment}
\begin{MyBoxedEnvironment}
\Text
\begin{MyBoxedEnvironment}
\textcolor{red}{\Text}
\end{MyBoxedEnvironment}
\end{MyBoxedEnvironment}
\end{document}
答案3
我不确定\ignorespaces
这里是否有用;尝试将其放在定义的最后\begin{...}
(这里,在计数器递增之后)。另外,为什么不将其包含\par\noindent
在环境定义中,就在之前\ignorespaces
?(如果我说了废话,请原谅;现在是凌晨 00:50,我正在看 TeX.SE 以在辛苦工作一天后休息;)。)
还,绝不将百分号放在数值常量后面!它们后面应该跟一个空格或换行符,如果你不遵守这个规则,总有一天,一个讨厌的、愚蠢的虫子会吃掉你!