![当章节标题后面跟着普通文本时,如何有条件地在章节标题后添加句点](https://linux22.com/image/455407/%E5%BD%93%E7%AB%A0%E8%8A%82%E6%A0%87%E9%A2%98%E5%90%8E%E9%9D%A2%E8%B7%9F%E7%9D%80%E6%99%AE%E9%80%9A%E6%96%87%E6%9C%AC%E6%97%B6%EF%BC%8C%E5%A6%82%E4%BD%95%E6%9C%89%E6%9D%A1%E4%BB%B6%E5%9C%B0%E5%9C%A8%E7%AB%A0%E8%8A%82%E6%A0%87%E9%A2%98%E5%90%8E%E6%B7%BB%E5%8A%A0%E5%8F%A5%E7%82%B9.png)
作为后续行动在小节标题后添加句号/点,我需要找到一种方法,当标题后面直接跟着普通文本时,有条件地在小节标题后面添加一个句号/点。如果后面跟着另一个标题或浮动文本,则不应有句号。在下面的示例中,第 1.1 节的标题不应以句号/点结尾,因为它后面紧跟着一个小节,而不是普通文本。
背景:这是我正在研究的 ANSI 标准的严格样式规范。
有人能帮忙吗?
\documentclass{scrartcl}
% Body Section Definitions
\RedeclareSectionCommand[
font=\sffamily\large,
runin=false,
beforeskip=10pt,
afterskip=4pt,
afterindent=false
]{section}
\RedeclareSectionCommand[
font=\normalsize\normalfont\bfseries,
runin=true,
beforeskip=10pt
]{subsection}
\RedeclareSectionCommand[
font=\normalsize\normalfont\bfseries,
runin=true,
beforeskip=10pt
]{subsubsection}
\renewcommand{\sectioncatchphraseformat}[4]{\hskip #2#3#4.}
\begin{document}
\section{Level 1 headings never end in a period}
\subsection{Level 2 headings should only end in a period if they are immediately followed by normal text}
\subsubsection{Level 3 is the same as level 2}
This section begins with normal text content, and its heading should end in a period. But the previous section should not end in a period because it is followed by another heading.
\end{document}
答案1
如果一个标题后面跟着另一个标题,则很难进行检测。但是,使用一些启发式方法,您可以检测到一个标题前面是否有另一个标题。在下面的例子中,我使用标题末尾的跳过来检测下一个级别的标题。为此,我使用做钩子用户手册第二部分中对 KOMA-Script 的解释:
\documentclass{scrartcl}
% Body Section Definitions
\RedeclareSectionCommand[
font=\sffamily\large,
runin=false,
beforeskip=10pt,
afterskip=4pt,
afterindent=false
]{section}
\RedeclareSectionCommand[
font=\normalsize\normalfont\bfseries,
runin=true,
beforeskip=10pt
]{subsection}
\RedeclareSectionCommand[
font=\normalsize\normalfont\bfseries,
runin=true,
beforeskip=10pt
]{subsubsection}
\makeatletter
\newcommand*{\storesubsectiondot}[1]{%
\ifdim\lastskip=4pt \else
\immediate\write\@mainaux{\string\global\string\@namedef{subsection\thesubsection dot}{.}}%
\fi
}
\AddtoDoHook{heading/preinit/subsubsection}{%
\storesubsectiondot
}
\newcommand*{\addsubsectiondot}{%
\@nameuse{subsection\thesubsection dot}%
}
\AtEndDocument{\storesubsectiondot{}}
\makeatother
\renewcommand{\sectioncatchphraseformat}[4]{\hskip #2#3#4\Ifstr{#1}{subsection}{\addsubsectiondot}{.}}
\begin{document}
\section{Level 1 headings never end in a period}
\subsection{Level 2 headings should only end in a period if they are
immediately followed by normal text}
Here we have normal text.
\subsubsection{Level 3 is the same as level 2}
This section begins with normal text content, and its heading should end in a
period. The previous section should also end in a period because it is
followed by normal text.
\section{Level 1 headings never end in a period}
\subsection{Level 2 headings should only end in a period if they are
immediately followed by normal text}
\subsubsection{Level 3 is the same as level 2}
This section begins with normal text content, and its heading should end in a period. But the previous section should not end in a period because it is followed by another heading.
\section{Level 1 headings never end in a period}
\subsection{Level 2 headings should only end in a period if they are
immediately followed by normal text}
This section begins with normal text content and therefore should have a dot.
\end{document}
还\AtEndDocument
用于检测最后一个标题后面是否跟着文本。也许这可以做得不那么具有启发性,因为最后一个标题后面应该总是跟着文本。如果需要,您还应该能够对较低级别执行类似操作。
但如你所见,这确实很复杂。因此,更手动的建议是:
\documentclass{scrartcl}
% Body Section Definitions
\RedeclareSectionCommand[
font=\sffamily\large,
runin=false,
beforeskip=10pt,
afterskip=4pt,
afterindent=false
]{section}
\RedeclareSectionCommand[
font=\normalsize\normalfont\bfseries,
runin=true,
beforeskip=10pt
]{subsection}
\RedeclareSectionCommand[
font=\normalsize\normalfont\bfseries,
runin=true,
beforeskip=10pt
]{subsubsection}
\DeclareRobustCommand{\sentencedot}{.}
\BeforeStartingTOC[toc]{\RenewCommandCopy\sentencedot\relax}
\begin{document}
\tableofcontents
\section{Level 1 headings never end in a period}
\subsection{Level 2 headings should only end in a period if they are
immediately followed by normal text\sentencedot}
Here we have normal text.
\subsubsection{Level 3 is the same as level 2\sentencedot}
This section begins with normal text content, and its heading should end in a
period. The previous section should also end in a period because it is
followed by normal text.
\section{Level 1 headings never end in a period}
\subsection{Level 2 headings should only end in a period if they are
immediately followed by normal text}
\subsubsection{Level 3 is the same as level 2\sentencedot}
This section begins with normal text content, and its heading should end in a period. But the previous section should not end in a period because it is followed by another heading.
\section{Level 1 headings never end in a period}
\subsection{Level 2 headings should only end in a period if they are
immediately followed by normal text\sentencedot}
This section begins with normal text content and therefore should have a dot.
\end{document}
答案2
由于没有一种干净的方法可以直接在 LaTeX 中执行此操作,所以我最终编写了一个排箫通过过滤器自动执行此操作潘多克:
import panflute as pf
HEADING_NAMES = [
"chapter",
"section",
"subsection",
"subsubsection",
"paragraph",
"subparagraph"]
def action(elem, doc):
if isinstance(elem, pf.Header):
if isinstance(elem.next, pf.Para):
if elem.level > 1:
before = inlatex(f"\\hypertarget{{{elem.identifier}}}{{%\n\\{HEADING_NAMES[elem.level]}[")
middle = inlatex(r"]{")
after = inlatex(fr".}}\label{{{elem.identifier}}}}}")
return [pf.Plain(before, *elem.content, middle, *elem.content, after)]
def main(doc=None):
return pf.run_filter(action, doc=doc)
if __name__ == "__main__":
main()
注意:此过滤器可以简化一次此功能已实施。