定义双重环境

定义双重环境

TLDR;如何定义像定理/证明中的“双重”环境(带有可选证明)?

我正在定义一个小图书馆它应该或多或少地表现得像定理/证明环境(xparse如果重要的话,我会用它来解析输入)。目前,我的代码是这样使用的:

\theoremProofEnd[my keys options]{thm}[mytitle]{My theorem}{My optional proof}

(当我没有证据时,我会删除最后的花括号)

但我希望它更接近人们定义定理和证明的通常方式,这样用户就不会改变太多。所以我希望能够像这样使用它:

\begin{proofAtEnd}[my keys options]{thm}[mytitle]
  My theorem
\end{proofAtEnd}
\begin{proof} %% <- This environment is optional
  My optinal proof
\end{proof}

但我不知道该怎么做...有什么想法吗?

梅威瑟: 在此处输入图片描述

\documentclass{article}

\usepackage{xparse}
\usepackage{mathtools}
\usepackage{amssymb, amsthm, amsmath, thm-restate}
\usepackage{thmtools} %%

\newtheorem{thm}{Theorem}[section]


\NewDocumentCommand\theoremProofEnd{O{}mO{}+m+g}{
  The options are ``#1''.
  \begin{restatable}[#3]{#2}{mymacro}
    #4
  \end{restatable}
  \IfNoValueTF{#5}{}{
    \begin{proof}[Custom proof]
      #5
    \end{proof}
  }
}

\begin{document}

\section{My minilib}
% Current syntax
\theoremProofEnd[options A, options B]{thm}[My optional title]{My theorem}{My proof}

\theoremProofEnd[options C]{thm}{My theorem without proof and title}

%% Wanted syntax:
% \begin{proofAtEnd}[options A, options B]{thm}[My optional title]
%   My theorem
% \end{proofAtEnd}
% \begin{proof}
%   My proof
% \end{proof}
% 
% \begin{proofAtEnd}[options C]{thm}
%   My theorem without proof and title
% \end{proofAtEnd}

\end{document}

答案1

由于评论内容有点多,因此这里给出一个答案。


首先,我要强调的是,只有清晰的语法才是好的语法。看起来像是一回事但实际作用完全不同的语法只会让人困惑。(好的)LaTeX 的优点之一是语法总是反映含义;\emph强调文本(无论这在印刷上意味着什么),\begin启动环境,\end结束环境。

因此,尽管理论上可行,但我强烈反对构建看起来像两个独立环境的语法,其中第二个环境实际上是一个可选参数。相反,您可以选择一些替代方案。(从现在开始,我将调用第一个环境head和第二个环境tail。)

  1. 您确实可以将环境分开。如果您想将某些信息从 传递headtail,请将其在 之外提供head。这有“泄漏”宏的缺点,并且您几乎无法控制head用户在 之后放置 的位置tail。但是,它将允许您使用所需的语法。

  2. 您可以在第一个环境中使用第二个环境。这在语义上是有意义的(tail是可选的部分 head) 并且还使设计环境变得相当容易(您可以使tail和它所需的信息在和head提供的分组之外自然不可用)。\beginend

  3. 您可以设计一个在 内使用的宏,head将 标记为 的所有\end{head}内容tail。这基本上与上一个选项相同,只是语法略有不同。

我倾向于选择 2,因为它是最直接的。


以下是所有三个选项的示例。我没有深入研究您的链接,但似乎您想要存储一些内容以供以后输出,因此我的head只是排版了一些东西,我的tail收集了其内容并引用了相应的head,然后由打印出来\printtails

当然,所有定义都可以根据用例进行改进,但我认为概念在这里变得清晰了。

\documentclass{article}

\usepackage{etoolbox}
\usepackage{calc}
\usepackage{collect}
\usepackage{hyperref}

\makeatletter
    \newcounter{head}
    \newcounter{tail}
    \def\@printtails{}
    \def\printtails{\@printtails\def\@printtails{}}
    \newenvironment{headA}[2]{%
        \par\vskip 1em\noindent%
        \refstepcounter{head}%
        \protected@edef\@currentlabelname{#2}%
        \label{#1}%
        % make information public
        \xdef\@lasthead@label{#1}%
        \xdef\@lasthead@title{#1}%
        \centering
        {\Large\bfseries Head~\thehead : #2\par}%
    }{%
        \par\vskip 1em%
    }
    \newenvironment{headB}[2]{%
        \par\vskip 1em\noindent%
        \refstepcounter{head}%
        \protected@edef\@currentlabelname{#2}%
        \label{#1}%
        % make {tail} available
        \def\tailB{\@tailB{#1}{#2}}%
        \let\endtailB\end@tailB
        \centering
        {\Large\bfseries Head~\thehead : #2\par}%
    }{%
        \par\vskip 1em%
    }
    \newenvironment{headC}[2]{%
        \par\vskip 1em\noindent%
        \refstepcounter{head}%
        \protected@edef\@currentlabelname{#2}%
        \label{#1}%
        % reset the \end{tail} hook
        \let\@maybeendtail\relax
        % make {tail} available
        \def\tailC{%
            \let\@maybeendtail\end@tailB
            \@tailB{#1}{#2}%
        }%
        \centering
        {\Large\bfseries Head~\thehead : #2\par}%
    }{%
        % use the \end{tail} hook
        \@maybeendtail
        \par\vskip 1em%
    }
    \newenvironment{@printtail}[2]{%
        \par\vskip 1em\noindent
        \setcounter{tail}{\expandafter\expandafter\expandafter\@firstoffive\csname r@#1\endcsname-1}%
        \refstepcounter{tail}%
        \protected@edef\@currentlabelname{The Tail of Head~\ref*{#1} ({\slshape\nameref*{#1}})}%
        \label{tailof:#1}%
        \begin{tabular}{|p{\textwidth-2\tabcolsep}|}%
        {\bfseries The Tail of Head~\ref{#1} ({\slshape\nameref{#1}})\quad}%
    }{%
        \end{tabular}%
        \par\vskip 1em%
    }
    \newenvironment{tailA}{%
        \xappto\@printtails{%
            \noexpand\begin{@printtail}{\@lasthead@label}{\@lasthead@title}%
                \expandafter\noexpand\csname @tailcontent@\@lasthead@label\endcsname
            \noexpand\end{@printtail}%
        }%
        \collectinmacro\@temp@tailcontent{}{}%
    }{%
        \endcollectinmacro
        \expandafter\expandafter\expandafter
        \gdef
        \expandafter\expandafter
        \csname @tailcontent@\@lasthead@label\endcsname
        \expandafter
        {\@temp@tailcontent}%
    }
    \newenvironment{@tailB}[2]{%
        \xappto\@printtails{%
            \noexpand\begin{@printtail}{#1}{#2}%
                \expandafter\noexpand\csname @tailcontent@#1\endcsname
            \noexpand\end{@printtail}%
        }%
        \def\@temp@headlabel{#1}%
        \collectinmacro\@temp@tailcontent{}{}%
    }{%
        \endcollectinmacro
        \expandafter\expandafter\expandafter
        \gdef
        \expandafter\expandafter
        \csname @tailcontent@\@temp@headlabel\endcsname
        \expandafter
        {\@temp@tailcontent}%
    }
\makeatother

\begin{document}

Have a look at tail~\ref{tailof:head:lorem} with the title \nameref{tailof:head:lorem}.
Or maybe consider tail~\ref{tailof:head:die} with the title \nameref{tailof:head:die}.

\begin{headA}{head:wine}{Better Than Grapes}
    In vino veritas.
\end{headA}

\begin{headA}{head:lorem}{This Is a Test}
    Lorem ipsum dolor sit amet.
\end{headA}
\begin{tailA}
    Well, it looks like Latin, but it doesn't actually mean anything, does it?
    Anyhow, people won't care if we just use it as filler.
\end{tailA}

\begin{headB}{head:something-else}{Something Else}
    Haec non sunt verba.
    \begin{tailB}
        Okay, then.
    \end{tailB}
\end{headB}

\begin{headC}{head:die}{Roll the die}
    Alea iacta est.
    \tailC
    Yes, I'm running out of sentences.
\end{headC}

\printtails

\end{document}

示例输出

相关内容