![如何使用 `amsthm` 在 TeXbook 中重现“危险弯曲练习”](https://linux22.com/image/472108/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%20%60amsthm%60%20%E5%9C%A8%20TeXbook%20%E4%B8%AD%E9%87%8D%E7%8E%B0%E2%80%9C%E5%8D%B1%E9%99%A9%E5%BC%AF%E6%9B%B2%E7%BB%83%E4%B9%A0%E2%80%9D.png)
我现在正在输入一个文档,并且有一个warning
用 创建的定理环境amsthm
。令我感兴趣的是 Knuth 的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
,并从 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}
我有两个问题:
- 到目前为止,
\clubpenalty=10000
适用于整个环境。我能以某种方式将其仅应用于此环境内的第一个段落吗?在TeXbook,Knuth 并没有解决这个问题,因为他要求每个“危险”的段落都应该有一个危险弯曲符号。 - 正如你所看到的警告 0.3,单线看起来不太好看。有办法补救吗?我建议,如果里面只有一条线
warning
,可以使用\textdbend
而\dbend
不是 脚的中心在底线上。我该如何检测?
amsthm
对于原始环境中缺失的任何内容或上述代码的改进,请随时提供反馈。