Я сейчас печатаю документ и у меня есть warning
среда теоремы, созданная с помощью amsthm
. Меня интригует то, что КнутTeXbookудалось поместить символ "опасный изгиб" перед тем, что выглядит как exercise
окружающая среда. Символ занимает ровно две строки, а жирный шрифт EXERCISE
и последующий текст обтекают этот символ, так что начинается третья строка и снова левое поле.
Мой вопрос в том, могу ли я воссоздать это с предпочтительно (измененными) amsthm
средами. Я знаю, что trivlist
в реализации сред возникают проблемы, но, возможно, можно воссоздать вид amsthm
сред без trivlist
. Обратите внимание, что опасный изгиб появляется даже перед заголовком (например, страница 5 изTeXbook).
решение1
Довольно хороший код в вашем ответе, но его можно улучшить. В частности, я использую \clubpenalties
вместо \clubpenalty
, поэтому мы можем
- не рекомендуется делать разрыв страницы после второй строки;
- не беспокойтесь о затирании
\clubpenalty
; - сброс
\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}
У меня два вопроса:
- На данный момент
\clubpenalty=10000
применяется ко всей среде. Могу ли я как-то применить его только к первому абзацу внутри этой среды? ВTeXbookКнут не решил эту проблему, поскольку потребовал, чтобы каждый «опасный» абзац был отмечен символом опасного изгиба. - Как вы можете видеть вПредупреждение 0.3, одна линия выглядит не очень красиво. Есть ли способ исправить это? Я бы предложил, что если внутри только одна линия
warning
, можно использовать\textdbend
вместо\dbend
чья нога и не ее центр находится на базовой линии. Как это обнаружить?
Не стесняйтесь оставлять отзывы о том, чего не хватает в исходных amsthm
средах, или об улучшениях в приведенном выше коде.