如何使用 `amsthm` 在 TeXbook 中重現“危險彎曲練習”

如何使用 `amsthm` 在 TeXbook 中重現“危險彎曲練習”

我現在正在輸入一個文檔,並擁有一個warning使用amsthm.讓我感興趣的是 Knuth 的教材設法將「危險彎道」符號放在看似環境的前面exercise。該符號恰好跨越兩行,並且粗體EXERCISE以及以下文字環繞該符號,以便第三行開始並再次開始左邊距。

我的問題是我是否可以使用更好的(修改後的)amsthm環境重新創建它。我知道trivlist在環境的實現中會導致問題,但也許可以在amsthm沒有trivlist.請注意,危險的彎曲甚至出現在標題之前(例如,第 5 頁)教材)。

答案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 的教材代碼。

\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適用於整個環境。我可以以某種方式將其僅應用於此環境中的第一段嗎?在教材,Knuth 沒有解決這個問題,因為他要求每個「危險」段落都應該有一個危險的彎曲符號。
  2. 正如你所看到的警告0.3,單行看起來不太好。有辦法解決這個問題嗎?我建議,如果裡面只有一條線warning,可以用whoose foot\textdbend代替\dbend,而且它的中心不在基線上。我如何檢測到這一點?

amsthm請隨意就原始環境中缺少的任何內容或對上述程式碼的改進提供回饋。

相關內容