买者自负 ...

买者自负 ...

我的文档中有一个“缩进”环境,我是这样创建的

\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@inlabellist

\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表明它可能破坏任何东西。出于这个原因,我还提出了另一种解决方案,将宏的补丁保留amsthmchangemargins环境中:

% 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

相关内容