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
。)
您确实可以将环境分开。如果您想将某些信息从 传递
head
到tail
,请将其在 之外提供head
。这有“泄漏”宏的缺点,并且您几乎无法控制head
用户在 之后放置 的位置tail
。但是,它将允许您使用所需的语法。您可以在第一个环境中使用第二个环境。这在语义上是有意义的(
tail
是可选的部分head
) 并且还使设计环境变得相当容易(您可以使tail
和它所需的信息在和head
提供的分组之外自然不可用)。\begin
end
您可以设计一个在 内使用的宏,
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}