我的文档中有一个“缩进”环境,我是这样创建的
\def\changemargin#1#2{
\list{}{\rightmargin#2\leftmargin#1}
\item[]
}
\let\endchangemargin=\endlist
那么如果环境中的第一个东西changemargin
是定理,它将添加一个不应该存在的额外垂直空间。我该如何防止这种情况?
检查
\documentclass[12pt]{article}
\usepackage{amsthm}
\usepackage[english]{babel}
\usepackage{blindtext}
\def\changemargin#1#2{\list{}{\rightmargin#2\leftmargin#1}\item[]}
\let\endchangemargin=\endlist
\newtheorem*{theorem}{Theorem}
\begin{document}
The rain in Spain falls mainly on the plain.
The rain in Spain falls mainly on the plain.
\begin{theorem}
This theorem has the correct spacing, because it's outside the changemargin environment.
\end{theorem}
The rain in Spain falls mainly on the plain. The rain in Spain falls mainly on the plain.
\begin{changemargin}{2cm}{2cm}
\begin{theorem}
This theorem has the wrong spacing, becuase it is the first thing in the change margin environment.
\end{theorem}
\end{changemargin}
The rain in Spain falls mainly on the plain. The rain in Spain falls mainly on the plain.
\begin{changemargin}{2cm}{2cm}
The rain in Spain falls mainly on the plain.
\begin{theorem}
This theorem has the correct spacing, because it is not the first thing in the changemargin environment.
\end{theorem}
\end{changemargin}
The rain in Spain falls mainly on the plain. The rain in Spain falls mainly on the plain.
\end{document}
一种解决方法是为定理创建一个宏,仅当它是 changemargin 环境中的第一件事时才使用。我想知道是否有更好的方法。或者,也许您可以建议一种更好的方法来临时更改边距(list
我想不是使用),这样就不会导致此问题。
更新:我对以下建议的答案感到困惑。以下代码抛出了缺失项目错误。
\documentclass[12pt]{article}
\usepackage{amsthm}
\usepackage{xparse}
\makeatletter
\NewDocumentEnvironment{changemargin}{O{3cm}D<>{3cm}}%
{\list{}{\leftmargin=#1\rightmargin=#1}\item\@inlabelfalse\@newlistfalse}
{\endlist}
\makeatother
\newtheorem*{theorem}{Theorem}
\begin{document}
\begin{changemargin}[0.9cm]<0.5cm>
The rain in Spain falls mainly on the plain.
\end{changemargin}
\begin{theorem}
The rain in Spain falls mainly on the plain.
\end{theorem}
\end{document}
答案1
已经给出了两个可行的答案;尽管如此,这两个答案都未能提供实际发生情况的详细解释,而且作者坦白承认,他们对这些答案为何有效的理解并不完美。事实上,很难——甚至对我来说——判断上述解决方案是否保证在任何合理情况下都能奏效。
在努力理清这个问题后,我头疼不已,于是决定写下这个答案,主要是因为显然不可能将它放在多条评论中。我希望能够对这个问题有所启发,但请注意,我的理解还不够完美。
通过 LaTeX 内核提供的默认功能定义的“类定理”环境以完全正确的方式与列表交互,如以下示例所示:
% My standard header for TeX.SX answers:
\documentclass[a4paper]{article} % To avoid confusion, let us explicitly
% declare the paper format.
\usepackage[T1]{fontenc} % Not always necessary, but recommended.
% End of standard header. What follows pertains to the problem at hand.
% \usepackage{amsthm}
\newenvironment*{changemargins}[2]{%
\list{}{%
\setlength\leftmargin {#1}%
\setlength\rightmargin{#2}%
}\item\relax
}{\endlist}
\newtheorem{thrm}{Theorem}
\begin{document}
``Theorem-like'' environments defined by means of the default facilities
provided by the \LaTeX\ kernel interact correctly with lists.
A theorem at the outer level:
\begin{thrm}
The ducks in dutch quack quaveringly on the docks.
\end{thrm}
Now inside a list: first making up an item by itself\ldots
\begin{enumerate}
\item
\begin{thrm}
The ducks in dutch quack quaveringly on the docks.
\end{thrm}
\item
\ldots and then after some text.
\begin{thrm}
The ducks in dutch quack quaveringly on the docks.
\end{thrm}
\item
A third item follows.
\end{enumerate}
In the same way, their behavior when used by themselves inside a
\texttt{changemargins} environment is absolutely normal:
\begin{changemargins}{2cm}{2cm}
\begin{thrm}
The ducks in dutch quack quaveringly on the docks.
\end{thrm}
\end{changemargins}
Another example, in which the ``theorem-like'' environment follows some text:
\begin{changemargins}{2cm}{2cm}
Some text, what suffices to get to the right margin\ldots\space
Well, perhaps just a little more.
\begin{thrm}
The ducks in dutch quack quaveringly on the docks.
\end{thrm}
\end{changemargins}
Uncommenting
\begin{verbatim}
\usepackage{amsthm}
\end{verbatim}
will break all the above examples, so it looks like the
\textsf{amsthm} package is the real culprit!
\end{document}
如果您取消注释该声明,您将看到“罪魁祸首”实际上是这个包。事实上,各种开关(如、等)\usepackage{amsthm}
的机制依赖于以下假设: -type 环境根据以下模式嵌套:\if@newlist
\if@inlabel
list
\begin{list}{...}{...}
\item
\begin{list}{...}{...}
\item
Text
换句话说,每个list
-type 环境(包括“ trivlist
-type”环境!)都应该直接包含一个\item
命令,或者一些等效的东西,在任何其他实际内容之前\item
,以免返回“缺失”错误。但我们可以看到(文件amsthm.sty
,第 186-199 行)amsthm
,该包在发出(第 123 行) a 之后\trivlist
,并不直接使用\item
命令(如 LaTeX 内核提供的相应功能一样),而是使用“等效命令”,尽管它不遵守开关\if@noparitem
。
以下示例修补了amsthm
包中的相关宏,使“类定理”环境在列表中也能按预期运行。我不喜欢使用包\patchcmd
中的功能etoolbox
,因为修补有点复杂,而且出于可读性的原因;大胆的人当然可以自由地做不同的事情。
% My standard header for TeX.SX answers:
\documentclass[a4paper]{article} % To avoid confusion, let us explicitly
% declare the paper format.
\usepackage[T1]{fontenc} % Not always necessary, but recommended.
% End of standard header. What follows pertains to the problem at hand.
\usepackage{amsthm}
\makeatletter
\def\deferred@thm@head#1{%
\if@noparlist
\@donoparitem
\else
\if@inlabel \indent \par \fi % eject a section head if one is pending
\if@nobreak
\adjust@parskip@nobreak
\else
\addpenalty\@beginparpenalty
\addvspace\@topsep
\addvspace{-\parskip}%
\fi
\global\@inlabeltrue
\fi
\everypar\dth@everypar
\global\sbox\@labels{\unhbox\@labels\normalfont#1}%
\ignorespaces
}
\makeatother
\newenvironment*{changemargins}[2]{%
\list{}{%
\setlength\leftmargin {#1}%
\setlength\rightmargin{#2}%
}\item\relax
}{\endlist}
\newtheorem{thrm}{Theorem}
\begin{document}
``Theorem-like'' environments defined by means of the default facilities
provided by the \LaTeX\ kernel interact correctly with lists.
A theorem at the outer level:
\begin{thrm}
The ducks in dutch quack quaveringly on the docks.
\end{thrm}
Now inside a list: first making up an item by itself\ldots
\begin{enumerate}
\item
\begin{thrm}
The ducks in dutch quack quaveringly on the docks.
\end{thrm}
\item
\ldots and then after some text.
\begin{thrm}
The ducks in dutch quack quaveringly on the docks.
\end{thrm}
\item
A third item follows.
\end{enumerate}
In the same way, their behavior when used by themselves inside a
\texttt{changemargins} environment is absolutely normal:
\begin{changemargins}{2cm}{2cm}
\begin{thrm}
The ducks in dutch quack quaveringly on the docks.
\end{thrm}
\end{changemargins}
Another example, in which the ``theorem-like'' environment follows some text:
\begin{changemargins}{2cm}{2cm}
Some text, what suffices to get to the right margin\ldots\space
Well, perhaps just a little more.
\begin{thrm}
The ducks in dutch quack quaveringly on the docks.
\end{thrm}
\end{changemargins}
\end{document}
请注意,为了使示例简单,我没有考虑语法xparse
:这是一个“正交”特征。
与其他补丁相比,此补丁具有以下优点:
我清楚地知道它为什么有效
;-)
;它适用于所有类型的列表环境。
然而,这并不意味着我完全确定它不会破坏任何东西;事实上,第 187 行的注释amsthm.sty
表明它可能破坏任何东西。出于这个原因,我还提出了另一种解决方案,将宏的补丁保留amsthm
在changemargins
环境中:
% My standard header for TeX.SX answers:
\documentclass[a4paper]{article} % To avoid confusion, let us explicitly
% declare the paper format.
\usepackage[T1]{fontenc} % Not always necessary, but recommended.
% End of standard header. What follows pertains to the problem at hand.
\usepackage{amsthm}
\makeatletter
\newcommand*\PatchAmsThmMacros{%
\def\deferred@thm@head##1{%
\if@noparlist
\@donoparitem
\else
\if@inlabel \indent \par \fi % eject a section head if one is pending
\if@nobreak
\adjust@parskip@nobreak
\else
\addpenalty\@beginparpenalty
\addvspace\@topsep
\addvspace{-\parskip}%
\fi
\global\@inlabeltrue
\fi
\everypar\dth@everypar
\global\sbox\@labels{\unhbox\@labels\normalfont##1}%
\ignorespaces
}%
}
\makeatother
\newenvironment*{changemargins}[2]{%
\list{}{%
\setlength\leftmargin {#1}%
\setlength\rightmargin{#2}%
}%
\PatchAmsThmMacros
\item\relax
}{\endlist}
\newtheorem{thrm}{Theorem}
\begin{document}
``Theorem-like'' environments defined by means of the default facilities
provided by the \LaTeX\ kernel interact correctly with lists.
A theorem at the outer level:
\begin{thrm}
The ducks in dutch quack quaveringly on the docks.
\end{thrm}
Now inside a list: first making up an item by itself\ldots
\begin{enumerate}
\item
\begin{thrm}
The ducks in dutch quack quaveringly on the docks.
\end{thrm}
\item
\ldots and then after some text.
\begin{thrm}
The ducks in dutch quack quaveringly on the docks.
\end{thrm}
\item
A third item follows.
\end{enumerate}
In the same way, their behavior when used by themselves inside a
\texttt{changemargins} environment is absolutely normal:
\begin{changemargins}{2cm}{2cm}
\begin{thrm}
The ducks in dutch quack quaveringly on the docks.
\end{thrm}
\end{changemargins}
Another example, in which the ``theorem-like'' environment follows some text:
\begin{changemargins}{2cm}{2cm}
Some text, what suffices to get to the right margin\ldots\space
Well, perhaps just a little more.
\begin{thrm}
The ducks in dutch quack quaveringly on the docks.
\end{thrm}
\end{changemargins}
\end{document}
正如您所见,这使得补丁与changemargins
环境一起工作,但不能与一起工作enumerate
。
答案2
注意:我不知道自己在做什么。
买者自负 ...
我添加了这些内容只是为了检查我没有无意中破坏间距。代码更改来自。此外,我更正了代替latex.ltx
的使用。#1
#2
\documentclass[12pt]{article}
\usepackage{amsthm}
\usepackage{xparse}
\makeatletter
\NewDocumentEnvironment{changemargin} {O{3cm}D<>{3cm}}
{%
\list{}{\leftmargin=#1\rightmargin=#2}\item
\if@inlabel\global\@inlabelfalse\fi
\@newlistfalse
}{%
\endlist
}
\makeatother
\newtheorem*{theorem}{Theorem}
\begin{document}
\begin{changemargin}[0.9cm]<0.5cm>
The rain in Spain falls mainly on the plain.
\begin{theorem}
The rain in Spain falls mainly on the plain.
\end{theorem}
\end{changemargin}
The rain in Spain falls mainly on the plain.
\begin{theorem}
The rain in Spain falls mainly on the plain.
\end{theorem}
\end{document}
答案3
编辑(重写和简化代码)
我重新研究了类定理环境的定义,我认为我找到了尝试使用时导致问题的原因\list
。也就是说,latex.ltx 中的第 4559-4566 行构成了定义的一部分\trivlist
:
\if@inlabel
\@noparitemtrue
\@noparlisttrue
\else
\if@newlist \@noitemerr \fi
\@noparlistfalse
\@topsep \@topsepadd
\fi
发生的事情是\list
设置了\@inlabeltrue
,反过来,这会导致在任何使用的环境的顶部添加额外的空间\trivlist
,其中有很多。为了阻止这种情况发生,我们只需禁用它。完成后,问题中的 MWE 会产生:
这是新代码,比我第一次尝试的代码简单得多:
\documentclass[12pt]{article}
\usepackage{amsthm}
\usepackage[margin=16mm,showframe]{geometry}% to show the margins
\usepackage{xparse}
\makeatletter
\NewDocumentEnvironment{changemargin}{O{3cm}D<>{3cm}}%
{\list{}{\leftmargin=#1\rightmargin=#2}\item%
\bgroup\@inlabelfalse\@newlistfalse}% change flags only in a group
{\egroup\endlist}
\makeatother
\newtheorem*{theorem}{Theorem}
\begin{document}
The rain in Spain falls mainly on the plain.
The rain in Spain falls mainly on the plain.
\begin{theorem}
This theorem has the correct spacing, because it's outside the changemargin environment.
\end{theorem}
The rain in Spain falls mainly on the plain. The rain in Spain falls mainly on the plain.
\begin{changemargin}[2cm]<2cm>
\begin{theorem}
This theorem has the right spacing and it is the first thing in the change margin environment.
\end{theorem}
\end{changemargin}
The rain in Spain falls mainly on the plain. The rain in Spain falls mainly on the plain.
\begin{changemargin}[2cm]<2cm>
The rain in Spain falls mainly on the plain.
\begin{theorem}
This theorem has the correct spacing, because it is not the first thing in the changemargin environment.
\end{theorem}
\end{changemargin}
The rain in Spain falls mainly on the plain. The rain in Spain falls mainly on the plain.
\end{document}
是\@newlistfalse
必要的,因为如果没有 latex 会出现错误,说缺少\item
。据我所知,添加这些行不会产生额外的副作用,\@inlabelfalse\@newlistfalse
因为它们只会阻止将额外的空间添加到任何使用的环境\trivlist
。当然,我可能遗漏了一些东西!
唯一值得一提的是,我已经使用from\changemargin
将 OP 的宏更改为环境\NewDocumentEnvironment
解析。环境有两个可选参数,可以单独使用,用于设置环境中的边距changemargin
。例如,
\begin{changemargin}[2cm]<4cm>
Here is the correct spacing.
\end{changemargin}
将左侧边距设置为 ,2cm
将右侧边距设置为4cm
。两个边距默认均为3mm
。