调整嵌套时环境的行为

调整嵌套时环境的行为

我想定义一个在嵌套时行为不同的环境。此环境应忽略环境开头和结尾的空格。当它不嵌套时,我可以按我的意愿工作。但是,当它嵌套时,我似乎无法获得所需的行为。

这里的第一个框是使用非嵌套版本所需的行为。我希望此环境的第二个嵌套版本表现得好像它不是嵌套的。但是,当前实现存在两个问题:

  1. 嵌套时,我需要添加尾随%\begin{MyBoxedEnvironment}%否则,中间会多出一行。(参见1在 MWE 中)。
  2. 嵌套时,我不能在此环境的开头后面留空行。可以通过手动添加来解决这个问题\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 以在辛苦工作一天后休息;)。)

还,绝不将百分号放在数值常量后面!它们后面应该跟一个空格或换行符,如果你不遵守这个规则,总有一天,一个讨厌的、愚蠢的虫子会吃掉你!

相关内容