Как воссоздать «опасное упражнение на изгиб» в TeXbook с помощью `amsthm`

Как воссоздать «опасное упражнение на изгиб» в TeXbook с помощью `amsthm`

Я сейчас печатаю документ и у меня есть warningсреда теоремы, созданная с помощью amsthm. Меня интригует то, что Кнут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окружения и вдохновился Кнутом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Кнут не решил эту проблему, поскольку потребовал, чтобы каждый «опасный» абзац был отмечен символом опасного изгиба.
  2. Как вы можете видеть вПредупреждение 0.3, одна линия выглядит не очень красиво. Есть ли способ исправить это? Я бы предложил, что если внутри только одна линия warning, можно использовать \textdbendвместо \dbendчья нога и не ее центр находится на базовой линии. Как это обнаружить?

Не стесняйтесь оставлять отзывы о том, чего не хватает в исходных amsthmсредах, или об улучшениях в приведенном выше коде.

Связанный контент