简单介绍一下背景,我正在写一篇论文,其中有定理(证明和推导)以及可能还有一些其他“定理”类型的环境。这个问题中的代码实际上运行良好,它正在做我想要的事情,但我觉得它可以被整理/改进。
对于方程,我选择了一种只针对实际证明或推导的编号格式。因此,这涉及存储现有方程编号、将其重置为零、更改样式(分别针对证明或推导)执行内容,然后恢复为现有值。
此外,一些推导/证明可以通过使用 multicol 来压缩,这是我之前的一篇文章阴影多色用于将证明/推导与周围内容区分开来,但是为了解决这个问题,这些格式样式已被删除。
下面是代码的精简版,它是一个完整的 MWE:
\documentclass{article}
%------------LOAD THE PACKAGES---------------%
%Load Single Packages Together
\usepackage{amsmath,amsfonts,amssymb,amsthm,mathtools,mathpazo,calc,ifthen}
\usepackage{environ,multicol,xcolor}
%DEFINE MY THEOREM STYLE
\let\oldproof\proof\let\proof\relax
\let\oldendproof\endproof\let\endproof\relax
\newcommand{\theoremLetter}{}
\newtheoremstyle{mythm} % name
{0pt} % Space above
{0pt} % Space below
{\small}% Body font
{} % Indent amount
{\bf\color{blue!50!black}}% Theorem head font
{.}% Punctuation after theorem head
{.5em} % Space after theorem head
{} % Theorem head spec (can be left empty, meaning ‘normal’)
\theoremstyle{mythm} %SELECT THE THEOREM
\newtheorem{derivation}{Derivation}
\newtheorem{proof}{Proof}
%Renew Formats, Equation, Figure, Table.
\renewcommand{\thederivation}{D\arabic{derivation}}
\renewcommand{\theproof}{P\arabic{proof}}
\newcounter{mytemp}%
\newenvironment{myenv}[3]{%
\def\envvar{#1}%
\def\mycols{#2}%
\par\vspace{0.5em} %add space
%Set the first letter depending on the type of environment.
%DERIVATION
\providecommand{\theoremLetter}{}%RESET
\ifthenelse{\equal{\envvar}{derivation}}{%
\renewcommand{\theoremLetter}{D}%
}{}%
%PROOF
\ifthenelse{\equal{\envvar}{proof}}{%
\renewcommand{\theoremLetter}{P}%
}{}%
\begin{\envvar}{\textbf{#3}}%
\setcounter{mytemp}{\value{equation}}%
\providecommand{\existingEquationFormat}{\theequation}%
\setcounter{equation}{0}%
\renewcommand{\theequation}{%
\theoremLetter\arabic{\envvar}.\arabic{equation}%
}%
\setlength{\abovedisplayskip}{0pt}%Set DisplaySkip Value.
\ifthenelse{\equal{\mycols}{1}}{}{\begin{multicols}{\mycols}}%
}{%BODY CONTENT OF ENVIRONMENT
\ifthenelse{\equal{\mycols}{1}}{}{\end{multicols}}%
\setcounter{equation}{\value{mytemp}}%
\renewcommand{\theequation}{\existingEquationFormat}%
\renewcommand{\existingEquationFormat}{\relax}%
\end{\envvar}%
}
以下是示例输出:
\begin{document}
\hrule
\section{Default Equation Format}
\begin{align}
y &= A\\
&= B
\end{align}
\hrule
\section{Sample Derivation and Proof (Multicolumn)}
\begin{myenv}{proof}{2}{Sample Proof}
Column 1
\begin{align}%
y &= A\\
&= B
\end{align}%
Column 2
\begin{align}
y &= C\\
&= D
\end{align}
\end{myenv}
\begin{myenv}{derivation}{2}{Sample Derivation}
Column 1
\begin{align}%
y &= A\\
&= B
\end{align}%
Column 2
\begin{align}
y &= C\\
&= D
\end{align}
\end{myenv}
\hrule
\section{Demonstrate Reset/Continuation of Format}
\begin{align}
y &= A\\
&= B
\end{align}
\hrule
\section{Further Derivation and Proof (Single Column)}
\begin{myenv}{proof}{1}{Another Proof}
\begin{align}%
y &= A\\
&= B
\end{align}%
\end{myenv}
\begin{myenv}{derivation}{1}{Another Derivation}
\begin{align}%
y &= A\\
&= B
\end{align}%
\end{myenv}
\hrule
\end{document}
上述代码产生以下结果:
在此输出中,可以清楚地看到以下特征:
- 推导与证明的编号样式是特定推导与证明的局部样式,该样式已更改为以 P 或 D 开头,以便清楚地将该编号与作为文档其余部分的标准方程编号区分开来。
- 标准方程编号被破坏,并在 thm 的两侧恢复
- 使用单列和多列模式。
所以我的问题是,如何在代码中替换以下内容:
%Set the first letter depending on the type of environment.
%DERIVATION
\providecommand{\theoremLetter}{}%RESET
\ifthenelse{\equal{\envvar}{derivation}}{%
\renewcommand{\theoremLetter}{D}%
}{}%
%PROOF
\ifthenelse{\equal{\envvar}{proof}}{%
\renewcommand{\theoremLetter}{P}%
}{}%
...因此,它采用特定定理样式的首字母(大写),目前,重新格式化实际上是“硬编码的”,我想消除这个限制。
有没有更有效的方法来完成我在这里所做的编码,我相信有,也许\newenvironment{myenv}{...}
可以完全删除。
答案1
您可以通过以下定义提取第一个字母,无需额外的包:
\def\tempa##1##2!{##1}%
\uppercase{\def\theoremLetter{\tempa#1!}}%%
该计划xstring
提供了类似的方法
\uppercase{\StrLeft{#1}{1}[\theoremLetter]}%
这是你修改后的环境
\newenvironment{myenv}[3]{%
\def\envvar{#1}%
\def\mycols{#2}%
\par\vspace{0.5em} %add space
%Set the first letter depending on the type of environment.
%DERIVATION
%Approach 1
\def\tempa##1##2!{##1}%
\uppercase{\def\theoremLetter{\tempa#1!}}%%
%Approach 2
% \uppercase{\StrLeft{#1}{1}[\theoremLetter]}%%
%
\begin{\envvar}{\textbf{#3}}%
\setcounter{mytemp}{\value{equation}}%
\providecommand{\existingEquationFormat}{\theequation}%
\setcounter{equation}{0}%
\renewcommand{\theequation}{%
\theoremLetter\arabic{\envvar}.\arabic{equation}%
}%
\setlength{\abovedisplayskip}{0pt}%Set DisplaySkip Value.
\ifthenelse{\equal{\mycols}{1}}{}{\begin{multicols}{\mycols}}%
}{%BODY CONTENT OF ENVIRONMENT
\ifthenelse{\equal{\mycols}{1}}{}{\end{multicols}}%
\setcounter{equation}{\value{mytemp}}%
\renewcommand{\theequation}{\existingEquationFormat}%
\renewcommand{\existingEquationFormat}{\relax}%
\end{\envvar}%
}
改进(从我的角度来看):
- 定义/重新定义在
\renewcommand
本地起作用。因此每次重置都是不必要的。 - 通常
setcounter
也是本地的,但是如果你加载包,calc
这些分配将始终是全局的。所以你必须重置计数器。 - 我更喜欢用这种方式对环境进行较小的定义,以便大多数作业都在额外的宏中完成。
如果您编写了一个包,那么您应该做更多的测试,无论环境是否存在。
\let\innerenv\relax
\let\endinnerenv\relax
\newenvironment{myenv}[3]{%
\def\envvar{#1}%
\par\vspace{0.5em} %add space
\begin{\envvar}{\textbf{#3}}%
\def\tempa##1##2!{##1}%
\uppercase{\def\theoremLetter{\tempa#1!}}%%
\setcounter{mytemp}{\value{equation}}%
\setlength{\abovedisplayskip}{0pt}%
\setcounter{equation}{0}%
\expandafter\let\expandafter\theequaction\csname the#1\endcsname
\ifnum#2>1
\def\innerenv{\begin{multicols}{#2}}%
\def\endinnerenv{\end{multicols}}%
\fi%
\innerenv
}{%BODY CONTENT OF ENVIRONMENT
\endinnerenv%
\setcounter{equation}{\value{mytemp}}%
\end{\envvar}%
}