对 \@afterheading、\@afterindentfalse 和其他环境中的段落的困惑

对 \@afterheading、\@afterindentfalse 和其他环境中的段落的困惑

我是一名软件包作者,正在为公司编写软件包。我试图提供类似于定理的环境,amsthm以便于使用。

我需要找到一种方法来实现以下行为:

  • 如果内容紧接着下一\begin{environment}行或从下一行开始,则应将其立即放置在环境标签之后,除非它跨越整个线宽,例如enumeratealign
  • 如果在环境开始处留有一个或多个空行,则内容需要从环境标签下方开始,并且第一行内容不能缩进(如标题后)。
  • 在新段落的环境中缩进仍然必须是可能的。

我研究了 MWE 中指出的以下想法,但没有一个能取得预期的结果。

    \documentclass[a4paper,landscape]{article}

    \usepackage{amsthm}
    \usepackage{thmtools}
    \usepackage{enumitem}
    \usepackage[a4paper,margin=1cm,landscape]{geometry}


    \makeatletter
    \declaretheorem[
        postheadhook={
            },
    ]{theoremA}

    \declaretheorem[
        postheadhook={
            \mbox{}
            },
    ]{theoremB}

    \declaretheorem[
        postheadhook={
            \mbox{}
            \@afterindentfalse
            \@afterheading
            },
    ]{theoremC}

    \declaretheorem[%
        postheadhook = {%
        \leavevmode
        \everypar{\setbox\z@\lastbox\everypar{}}
        },
    ]{theoremD}

    \declaretheorem[%
        postheadhook = {%
        \setbox\z@\lastbox
        },
    ]{theoremE}
    \makeatother

    \begin{document}

    \begin{minipage}[t]{0.3\linewidth}
        \setlength{\parindent}{1cm}
        \section{Type A}
        \begin{theoremA}
            This line is exactly where it ought to be.

            This other line is indented, as it constitutes a new paragraph inside the theorem. This is fine.
        \end{theoremA}

        \begin{theoremA}

            This line is starting right after the label, which it should \textbf{not} do.

            This other line is indented, as it constitutes a new paragraph inside the theorem.
        \end{theoremA}

        \begin{theoremA}
            \begin{enumerate}
                \item line A
                \item line B
            \end{enumerate}
            The enumeration should start on its own line, and \textbf{not} after the label.
        \end{theoremA}
    \end{minipage}
    \hfill
    \begin{minipage}[t]{0.3\linewidth}
        \setlength{\parindent}{1cm}
        \section{Type B}

        \begin{theoremB}
            This line is correctly broken to a new line and staring right after the theorem label as intended.

            This other line is indented, as it constitutes a new paragraph inside the theorem. This is as intended.
        \end{theoremB}

        \begin{theoremB}

            This line is correctly starting on a new line, however, I do \textbf{not} want it to be indented (just for the first line).

            This other line is indented, as it constitutes a new paragraph inside the theorem.
        \end{theoremB}

        \begin{theoremB}
            \begin{enumerate}
                \item line A
                \item line B
            \end{enumerate}
            The enumeration now starts on its own line as intended. Notice the topsep is being kept as intended.
        \end{theoremB}
    \end{minipage}
    \hfill
    \begin{minipage}[t]{0.3\linewidth}
        \setlength{\parindent}{1cm}
        % \everypar{ASDF}
        \section{Type C}

        \begin{theoremC}
            This line is starting right after the label as intended.

            This other line is \textbf{not} indented, and this is \textbf{not} the behaviour I expect.

            However, if I add another line, this one gets indented as expected.
        \end{theoremC}
        %
        \begin{theoremC}

            This line is correctly moved to a new line.

            This other line is indented, as it constitutes a new paragraph inside the theorem.
        \end{theoremC}
        %
        \begin{theoremC}
            \begin{enumerate}
                \item line A
                \item line B
            \end{enumerate}
            The enumeration now starts on its own line. Good. However, the topsep is ignored, which is \textbf{not} what I want.
        \end{theoremC}
    \end{minipage}

    \pagebreak

    \begin{minipage}[t]{0.3\linewidth}
        \setlength{\parindent}{1cm}
        \section{Type D}

        \begin{theoremD}
            This line is starting right after the label as intended.

            This other line is \textbf{not} indented, and this is \textbf{not} the behaviour I expect.

            However, if I add another line, this one gets indented as expected.
        \end{theoremD}
        %
        \begin{theoremD}

            This line is correctly moved to a new line and correctly indented.

            This other line is indented, as it constitutes a new paragraph inside the theorem.
        \end{theoremD}
        %
        \begin{theoremD}
            \begin{enumerate}
                \item line A
                \item line B
            \end{enumerate}
            The enumeration now starts on its own line. Good. However, the topsep is ignored, which is \textbf{not} what I want.
        \end{theoremD}

        \textbf{In short, this behaves exactly like Type~C.}
    \end{minipage}
    \hfill
    \begin{minipage}[t]{0.3\linewidth}
        \setlength{\parindent}{1cm}
        \section{Type E}

        \begin{theoremE}
            This line is exactly where it ought to be.

            This other line is indented, as it constitutes a new paragraph inside the theorem. This is fine.
        \end{theoremE}

        \begin{theoremE}

            This line is starting right after the label, which it should \textbf{not} do.

            This other line is indented, as it constitutes a new paragraph inside the theorem.
        \end{theoremE}

        \begin{theoremE}
            \begin{enumerate}
                \item line A
                \item line B
            \end{enumerate}
            The enumeration should start on its own line, and \textbf{not} after the label.
        \end{theoremE}

        \textbf{In short, this behaves exactly like Type~A.}
    \end{minipage}
    \hfill
    \begin{minipage}[t]{0.3\linewidth}
        \setlength{\parindent}{1cm}
        \section{Future tests}
    \end{minipage}


    \end{document}

请原谅冗长的 MWE,但我向你保证,这是显示比较的最少结构。

我的示例编译如下:

在此处输入图片描述

请参阅内联注释,了解 MWE 与期望/预期行为的具体偏差。

我很高兴被指向另一个方向,只是记住我不能只用于文档作者,或者要求他们在文档中\noindent输入空白。\mbox{}

补充1:

我按照给出的答案和评论中的建议测试了两个新案例(类型 D 和类型 E)。但是,它们没有提供令人满意的答案。请参阅所附的屏幕截图:

在此处输入图片描述

附加代码已直接添加到 MWE。

答案1

摘自 source2e.pdf 的 ltpara.dtx 章节:

因此,TEX 提供了在段落开头(或多或少)放入一些特殊代码 \everypar以获得控制权的可能性。例如,在 LaTeX 和许多软件包中,有时会使用如下特殊代码:

\everypar{{\setbox\z@\lastbox}\everypar{} ...}

这将再次删除段落缩进框(该框已由 TEX 放置),然后重置\everypar,使其在下一个段落开始时不执行任何操作,然后执行其想要执行的任何操作,例如,在\item列表中,它将在段落文本前面排版标签。但是,只有一个这样的\everypar标记寄存器,如果不同的软件包和/或内核都尝试在此处添加自己的代码,则协调将非常困难,甚至不可能。

\@afterheading包含此代码,尽管它首先检查\if@afterindent。但您真正需要的只是位\everypar。最大的问题是 Theorem 是否已经在使用\everypar


定理似乎测试标签并吸收任何\pars。 \null不足以满足测试,但是\strut

\documentclass[a4paper,landscape]{article}

    \usepackage{amsthm}
    \usepackage{thmtools}
    \usepackage{enumitem}
    \usepackage[a4paper,margin=1cm,landscape]{geometry}


    \declaretheorem{theoremA}

    \begin{document}

    \begin{minipage}[t]{0.3\linewidth}
        \setlength{\parindent}{1cm}
        \section{Type A}
        \begin{theoremA}
            This line is exactly where it ought to be.

            This other line is indented, as it constitutes a new paragraph inside the theorem. This is fine.
        \end{theoremA}

        \begin{theoremA}\strut\newline
            This line is no longer starting right after the label, as desired.

            This other line is indented, as it constitutes a new paragraph inside the theorem.
        \end{theoremA}

        \begin{theoremA}\strut%\vspace{\dimexpr \itemsep-\baselineskip}
            \begin{enumerate}
                \item line A
                \item line B
            \end{enumerate}
            The enumeration should start on its own line, and \textbf{not} after the label.
        \end{theoremA}
    \end{minipage}
    
    \end{document}

相关内容