如何使用 `amsthm` 在 TeXbook 中重现“危险弯曲练习”

如何使用 `amsthm` 在 TeXbook 中重现“危险弯曲练习”

我现在正在输入一个文档,并且有一个warning用 创建的定理环境amsthm。令我感兴趣的是 Knuth 的TeXbook设法将“危险弯道”符号放在看起来像是环境的符号前面exercise。该符号正好跨越两行,粗体EXERCISE以及下面的文本环绕该符号,因此第三行再次开始并位于左边距。

我的问题是,我是否可以使用经过修改的amsthm环境重新创建此内容。我知道trivlist在环境的实施中会导致问题,但有可能amsthm在没有的情况下重新创建环境的外观trivlist。请注意,危险的弯曲甚至出现在标题之前(例如第 5 页TeXbook)。

答案1

您的答案中的代码非常好,但可以改进。特别是我使用\clubpenalties而不是\clubpenalty,因此我们可以

  1. 不鼓励在第二行之后分页;
  2. 不必担心破坏\clubpenalty
  3. \clubpenalties用钩子复位。

我还排版了标题段落开始,因此我们可以使用\label而不必担心空格。

对于一行警告,我们检查\prevgraf第一段的末尾,如果是 1,则会生成一个空行,并且没有可能的分页符。

\documentclass{article}

\usepackage{manfnt} % for \dbend
\usepackage{lipsum} % for testing

\counterwithin{equation}{section}

\newlength{\dangerwidth} % width of \dbend
\settowidth{\dangerwidth}{\dbend}
\addtolength{\dangerwidth}{1em} % add any extra space between \dbend and text

\NewDocumentEnvironment{warning}{o}{%
  % I mostly use equation counter, feel free to use any other one
  % default \topsep before theorem environment
  \par\addvspace{\topsep}
  % no line break after first line and discourage after second line
  \clubpenalties=3 10000 5000 0 
  % after first paragraph, reset \clubpenalties
  \AddToHookNext{para/end}{\clubpenalties=0 }%
  % after first paragraph, count the number of lines, if one add an empty line and no page break
  \AddToHookNext{para/after}{\ifnum\prevgraf=1 \nopagebreak\hbox{}\fi}%
  % specifying indentation of first two lines
  \hangindent=\dangerwidth \hangafter=-2 
  % step the associated counter
  \refstepcounter{equation}%
  % store the start so to allow for \label
  \everypar\expandafter{%
    % remove the indentation box
    {\setbox0=\lastbox}% <----  !!!!!!!
    % zero width \dbend, shifted to left border
    \makebox[0pt]{\hspace*{-\hangindent}\dbend\hfill}%
    % theorem name and number
    \textbf{Warning \theequation}%
    % the attribution, if given
    \IfValueT{#1}{ (#1)}%
    % punctuation and space after
    \textbf{.}\hspace*{5pt plus 1pt minus 1pt}%
    % reset \everypar
    \everypar{}%
  }%
  % ignore spaces at the beginning
  \ignorespaces
}{
  % end the paragraph
  \par
  % default space after the environment
  \addvspace{\topsep}%
}

\begin{document}

\lipsum[66]

\begin{warning}[a note]\label{xyz}
    \lipsum[66]

    \lipsum[66]
\end{warning}

\begin{warning}
    \lipsum[66]
\end{warning}

\lipsum[66]

\begin{warning}
    One single line looks weird.
\end{warning}

Let's see the reference \ref{xyz}

\lipsum[66]

\end{document}

在此处输入图片描述

答案2

经过多次修改,我认为我得到了一个令人满意的结果。我从环境中获取了基本参数amsthm,并从 Knuth 的TeXbook代码。

\documentclass{article}

\usepackage{manfnt} % for \dbend
\usepackage{lipsum} % for testing

\newlength{\dangerwidth} % width of \dbend
\settowidth{\dangerwidth}{\dbend}
\addtolength{\dangerwidth}{1em} % add any extra space between \dbend and text

\newenvironment{warning}[1][]{
    \begingroup % local definition
    \stepcounter{equation} % I mostly use equation counter, feel free to use any other one
    \par\addvspace{\topsep} % default \topsep before theorem environment
    \clubpenalty=10000 % no line break after first line
    \hangindent=\dangerwidth \hangafter=-2 % specifying indentation of first two lines
    \noindent\makebox[0pt]{\hspace*{-\hangindent}\dbend\hfill}% % zero width \dbend, shifted to left boarder
    \textbf{Warning \thesection.\theequation}% % theorem name and number
    \if\relax\detokenize{#1}\relax\else % optional argument, check if empty
        \space(#1)% % if so, type optional argument in parenthesis
    \fi
    \textbf{.}\hspace*{5pt plus 1pt minus 1pt}\ignorespaces % add default rubber after theorem header
}{
    \par\addvspace{\topsep}\endgroup % default \topsep after environment
}

\begin{document}

\lipsum[66]

\begin{warning}[a note]
    \lipsum[66]

    \lipsum[66]
\end{warning}

\begin{warning}
    \lipsum[66]
\end{warning}

\lipsum[66]

\begin{warning}
    One single line looks weird.
\end{warning}

\end{document}

在此处输入图片描述

我有两个问题:

  1. 到目前为止,\clubpenalty=10000适用于整个环境。我能以某种方式将其仅应用于此环境内的第一个段落吗?在TeXbook,Knuth 并没有解决这个问题,因为他要求每个“危险”的段落都应该有一个危险弯曲符号。
  2. 正如你所看到的警告 0.3,单线看起来不太好看。有办法补救吗?我建议,如果里面只有一条线warning,可以使用\textdbend\dbend不是 脚的中心在底线上。我该如何检测?

amsthm对于原始环境中缺失的任何内容或上述代码的改进,请随时提供反馈。

相关内容