如何修剪 `\NewEnviron` 中 `\BODY` 的空格

如何修剪 `\NewEnviron` 中 `\BODY` 的空格

以下是我定义的\ansproof环境代码(深蓝色\proof环境)。问题是,在 的原始版本中\proof\begin{proof}\n\n\n\end{proof}替换\n为键入“enter”),这些空行将被忽略,但在我的环境中并非如此\ansproof,因为\BODY仍然与那些 一起读取\n,并且不会被识别为\empty。这导致当证明为空时​​ QED 符号出现在另一行上。

\makeatletter
\newenvironment{ansproofbase}[1][\proofname]{\par
  \pushQED{\hfill\textcolor{NavyBlue}{\qed}}%
  \normalfont\topsep6\p@\@plus6\p@\relax
  \trivlist
  \item[\hskip\labelsep\textcolor{NavyBlue}{\textit{#1.}}]\textcolor{NavyBlue}{\ignorespaces}
}{%
  \popQED\endtrivlist\@endpefalse
}
\makeatother
\NewEnviron{ansproof}{%
    \ifx\BODY\empty%
        \begin{ansproofbase}\end{ansproofbase}%
    \else%
        \textcolor{NavyBlue}{%
            \begin{ansproofbase}%
                \BODY%
            \end{ansproofbase}%
        }%
    \fi%
}

通过 chatgpt,我尝试了\if\relax\detokenize\expandafter{\BODY}\relax,但也没有用。

---- 编辑 1:小例子 ----

\begin{ansproof}

\end{ansproof}
\begin{proof}

\end{proof}

结果: 示例结果

---- 编辑 2:完整示例 ----

\documentclass{article}
\usepackage{graphicx, amssymb, amsmath, amsthm, xcolor, environ, xparse}

\definecolor{NavyBlue}{RGB}{0,0,128}
\makeatletter
\newenvironment{ansproofbase}[1][\proofname]{\par
  \pushQED{\hfill\textcolor{NavyBlue}{\qed}}%
  \normalfont\topsep6\p@\@plus6\p@\relax
  \trivlist
  \item[\hskip\labelsep\textcolor{NavyBlue}{\textit{#1.}}]\textcolor{NavyBlue}{\ignorespaces}
}{%
  \popQED\endtrivlist\@endpefalse
}
\makeatother
\NewEnviron{ansproof}{%
    \ifx\BODY\empty%
        \begin{ansproofbase}\end{ansproofbase}%
    \else%
        \textcolor{NavyBlue}{%
            \begin{ansproofbase}%
                \BODY%
            \end{ansproofbase}%
        }%
    \fi%
    \vspace{-0.8em}
}

\begin{document}
\noindent Small Example:
\begin{ansproof}
    
\end{ansproof}
\begin{proof}
    
\end{proof}
\end{document}

结果: 完整示例

---- 编辑 3:更微妙的例子 ----

(只需将以下内容添加到上一个示例的文档内)使用下面答案中提到的@Steven B. Segletes,NavyBlue (ans)proof 看起来与上例中的证明完全一样。但是,环境内的空间没有被修剪,\if\relax\BODY\relax这真的很奇怪。\ifx\BODY\empty\item\enumerate

\begin{enumerate}
    \item Example item
    \begin{ansproof}
    
    \end{ansproof}
    \begin{proof}
        
    \end{proof}
\end{enumerate}

微妙的例子结果

答案1

感谢 David 和 egreg 指出我原始答案中的缺陷。

我们想\if对 进行测试,\BODY而不是\ifx因为我们想测试完整的\BODY而不仅仅是 的第一个标记\BODY

问题在于\BODY,对于 OP 引用的情况,\par其中包含一个孤独,并且 OP 希望将这种情况视为空的\BODY

因此,我在这里执行一个 token 循环\BODY来(暂时)消除\partoken,然后检查此结果的去 token 化是否为空白。我用于测试的实际代码是

\if\relax\detokenize\expandafter{\the\cytoks}\relax

其中\cytoks是包含 的标记的标记列表,\BODY其中所有\par标记均已删除。

我还移动了环境\textcolor内部ansproofbase,以避免在某些情况下出现奇怪的间距。

以下是 MWE:

\documentclass{article}
\usepackage{graphicx, amssymb, amsmath, amsthm, xcolor, environ, xparse,tokcycle}
\Macrodirective{\ifx\par#1\else\addcytoks{#1}\fi}

\definecolor{NavyBlue}{RGB}{0,0,128}
\makeatletter
\newenvironment{ansproofbase}[1][\proofname]{\par
  \pushQED{\hfill\textcolor{NavyBlue}{\qed}}%
  \normalfont\topsep6\p@\@plus6\p@\relax
  \trivlist
  \item[\hskip\labelsep\textcolor{NavyBlue}{\textit{#1.}}]\textcolor{NavyBlue}{\ignorespaces}
}{%
  \popQED\endtrivlist\@endpefalse
}
\makeatother
\NewEnviron{ansproof}{%
    \expandafter\tokcyclexpress\expandafter{\BODY}%
    \if\relax\detokenize\expandafter{\the\cytoks}\relax%
        \begin{ansproofbase}\end{ansproofbase}%
    \else
        \begin{ansproofbase}%
            \textcolor{NavyBlue}{\BODY}%
        \end{ansproofbase}%
    \fi%
    \vspace{-0.8em}
}

\begin{document}
\noindent Small Example:
    \begin{ansproof} \end{ansproof}

    \begin{ansproof}\mbox{x}\end{ansproof}

    \begin{ansproof}

    \end{ansproof}

    \begin{ansproof}
not empty
    \end{ansproof}

    \begin{proof}
        
    \end{proof}

\makeatletter
\begin{enumerate}
    \item Example item with space
    \begin{ansproof} \end{ansproof}

    \item Example item with leading mbox
    \begin{ansproof}\mbox{x}\end{ansproof}

    \item Example item with blank line
    \begin{ansproof}
    
    \end{ansproof}

    \item Example item with text
    \begin{ansproof}
      not empty
    \end{ansproof}

    \item Example item
    \begin{proof}
        
    \end{proof}
\end{enumerate}
\end{document}

在此处输入图片描述

答案2

我不确定 的目的ansproofbase是什么。一开始就设置颜色。

使用起来更容易:想法是从环境主体中expl3剥离标记并查看是否只剩下空白。\par

\documentclass{article}
\usepackage{amsthm,xcolor}

\definecolor{NavyBlue}{RGB}{0,0,128}

\ExplSyntaxOn

\NewDocumentEnvironment{ansproof}{O{\proofname}+b}{%
  \par\color{NavyBlue}
  \begin{proof}[#1]
  \twilight_if_empty:nF { #2 } { #2 }
  \end{proof}
}{}

\prg_new_protected_conditional:Nnn \twilight_if_empty:n { T,F,TF }
 {
  \tl_set:Nn \l_tmpa_tl { #1 }
  \tl_remove_all:Nn \l_tmpa_tl { \par }
  \tl_if_blank:VTF \l_tmpa_tl { \prg_return_true: } { \prg_return_false: }
 }

\ExplSyntaxOff

\begin{document}

\noindent Small Example:

\begin{ansproof}
    
\end{ansproof}

Something in between

\begin{ansproof}[Interesting proof]
Here it is!
\end{ansproof}

Something at the end

\end{document}

在此处输入图片描述

相关内容