我想知道是否有可能在 \part 之上创建一个新的分段级别。我已经浏览了相当多似乎相关但实际上没有帮助的主题。有人建议将所有级别向下推一级,但 (i) 这将消除使用子段落的可能性(可以吗?)并且 (ii) 我对使用预先存在的设置可以获得的输出非常满意,而重新分配每个级别会相当麻烦(或者有什么简单的方法可以做到这一点?)。
简而言之,是否可以定义某种 \superpart{},其设置与 \part{} 相同,但写得更大或大写?
我希望我的问题足够清楚,并提前感谢您的回答。
文档结构如下:
\documentclass[a4paper, 10pt]{book}
\usepackage{blindtext}
\renewcommand{\thesection}{\arabic{section}}
\setcounter{secnumdepth}{5}
\begin{document}
\part{This is part1}
\chapter{Chapter title}
\section{This is a section}
\section{Section}
\subsection{Subsection}
\subsubsection{Subsubsection}
\paragraph{Paragraph}
\subparagraph{Subparagraph}
\blindtext
\end{document}
答案1
当然。没有理由你不能向任何方向无限前进。
在 中book
, 的部分级别\part
为 -1。您只需定义一个级别为 -2 的级别即可。
深入研究book.cls
你会发现相关的定义\part
:
\newcommand\part{%
\if@openright
\cleardoublepage
\else
\clearpage
\fi
\thispagestyle{plain}%
\if@twocolumn
\onecolumn
\@tempswatrue
\else
\@tempswafalse
\fi
\null\vfil
\secdef\@part\@spart}
\def\@part[#1]#2{%
\ifnum \c@secnumdepth >-2\relax
\refstepcounter{part}%
\addcontentsline{toc}{part}{\thepart\hspace{1em}#1}%
\else
\addcontentsline{toc}{part}{#1}%
\fi
\markboth{}{}%
{\centering
\interlinepenalty \@M
\normalfont
\ifnum \c@secnumdepth >-2\relax
\huge\bfseries \partname\nobreakspace\thepart
\par
\vskip 20\p@
\fi
\Huge \bfseries #2\par}%
\@endpart}
\def\@spart#1{%
{\centering
\interlinepenalty \@M
\normalfont
\Huge \bfseries #1\par}%
\@endpart}
\def\@endpart{\vfil\newpage
\if@twoside
\if@openright
\null
\thispagestyle{empty}%
\newpage
\fi
\fi
\if@tempswa
\twocolumn
\fi}
我们不要仅仅通过剪切、粘贴和编辑来获得\superpart
,而是用二十一世纪的 LaTeX 和来重新定义\NewDocumentCommmand
。
样式中的分段命令模板xparse
是¹:
\NewDocumentCommand{\superpart}{s O{#3} m}{%
这表示我们的命令有一个可选的星号形式(s
),一个可选参数(默认为强制参数的值),然后是一个强制参数。
然后我们可以做一些事情\part
来为超级部分标题打开一个新的单列页面:
\if@openright % ❶
\cleardoublepage
\else
\clearpage
\fi
\thispagestyle{plain}%
\if@twocolumn
\onecolumn
\@tempswatrue
\else
\@tempswafalse
\fi % ➀
\null \vfil % ❷
到目前为止需要注意几点。在我标记 ❶ 的行上,我们检查是否应该在 recto² 页面上,如果是,则\cleardoublepage
转到奇数页。否则,我们只需开始一个新页面。还请注意,我们有一些命令,@
这意味着我们需要在类/包文件中,或者将我们的定义括在\makeatletter
...中\makeatother
。
在标有 ❷ 的行上,\null
之前的\vfil
是一个空框。通常,页面顶部的任何粘连都会被忽略。这使我们能够将超部分标题置于页面中央。
接下来,我们检查是否对超级部分进行编号(我们可能正在编号),这取决于是否secnumdepth
≥-2 以及我们是否正在进行星号形式。
我们将在本文末尾解释 ➀ 的含义。
\IfBooleanF{#1}{%
\ifnum\c@senumdepth > -3\relax
\refstepcounter{superpart}%
\addcontentsline{toc}{superpart}{\thesuperpart\hspace{1em}#2}%
\else
\addcontentsline{toc}{superpart}{#2}%
\fi
\superpartmark{#2}% ❸
}%
我对 ❸ 处的逻辑做了一点小改动,引入了一个我们稍后会定义的新命令。book
假设您不希望零件名称进入标题,并且不提供这样做的功能。但也许你想。
接下来我们实际打印标题。
{%
\centering
\interlinepenalty \@M % ❹
\normalfamily
\IfBooleanF{#1}{%
\ifnum\c@secnumdepth > -3\relax % ❺
\Huge % ❻
\bfseries
\superpartname\nobreakspace\thesuperpart
\par
\vskip 20\p@
\fi
}%
}
❹ 处的设置是错误的,也是一个坏主意,但这是 LaTeX 37 年来一直在做的事情,所以我不会改变它。它使 LaTeX 不愿意在段落内换行。这意味着 (a) 如果标题长度超过一页,则(超级)部分编号将被推到页面底部;(2) 如果不带编号的标题仍然太长而无法放在一页上,它就会溢出页面底部。故事的道德启示 不要使用长标题。
我原本以为应该使用临时开关,以避免重复 ❺ 和上一个代码块中看似相同的逻辑,但仔细检查就会发现,由于对\superpartmark
上面的调用,这两种情况并不完全相同。 不急于尽早优化的好例子。 另外,LaTeX 提供了@tempswa
但没有@tempswb
。
我讨厌 LaTeX 的尺寸选择命令,比如 ❻ 中的命令。它们是位图字体时代的遗物,锁定在 Knuth 对字体大小的 1.2 次方的特殊选择上。“真正的”印刷师永远不会将某些东西设置为 17.28pt。较小的尺寸甚至更糟糕,因为 LaTeX 使用它来表示“比正常文本尺寸小两个尺寸”和“脚注的格式”。就我个人而言,我认为,至少所有尺寸调整命令都应该是名称中\footnotesize
包含的私有命令。@
最后,我们总结一下 superpart 页面,
\vfil\newpage
\if@twoside
\if@openright
\null
\thispagestyle{empty}% ❼
\newpage
\fi
\fi
\if@tempswa % ❽
\twocolumn
\fi
\@afterheading ❾
}
在 ❼ 处,我们确保如果在右页上打开设置,我们会插入一个没有页眉或页脚的空白页。当然,正如我们在 的设置中提到的那样\interlineskip
,不能保证我们的部分标题实际上会打印在一页上(尽管有是保证如果它拆分到多个页面中会很难看)。
❽还记得在第一节中我们设置\@tempswatrue
是否处于两列模式吗?现在我们可以利用该值再次恢复两列模式。
❾ 处的命令不是 的一部分\part
,但可以说应该是 的一部分。LaTeX 通常会抑制节标题后的文本缩进³,在这种情况下没有理由不这样做。
现在我们有一些事情要做。首先,我们为我们的超级部分声明一个计数器:
\newcounter{superpart}
\thesuperpart
如果我们不想使用默认的阿拉伯数字,我们也会重新定义。如果你想使用xparse
-style 定义,你需要这样写,例如,
\RenewExpandableDocumentCommand{\thesuperpart}{}{\Roman{superpart}}
如果我们改用\RenewDocumentCommand
,我们会发现目录中打印的数字是错误的,我们会很伤心。通常,我们希望命令是健壮的,并且在写入目录等时不会改变,但对于打印计数器值之类的事情,我们希望相反,这样我们实际上会写入MCMLXXXVIII
而不是\thesuperpart
。
如果我们想用 superparts 来编号零件,我们还需要添加
\numberwithin{part}{superpart}
为了打印目录中的行,我们需要定义\l@superpart
。这不是特别有趣,所以我只是对做了一些小的book
修改\l@part
:
\NewDocumentCommmand\l@superpart{m}{%
\ifnum \c@tocdepth >-3\relax
\addpenalty{-\@highpenalty}%
\addvspace{2.25em \@plus\p@}%
\setlength\@tempdima{3em}%
\begingroup
\parindent \z@ \rightskip \@pnumwidth
\parfillskip -\@pnumwidth
{\leavevmode
\large \bfseries #1\hfil
\hb@xt@\@pnumwidth{\hss #2%
\kern-\p@\kern\p@}}\par
\nobreak
\global\@nobreaktrue
\everypar{\global\@nobreakfalse\everypar{}}%
\endgroup
\fi}
我们需要定义要打印的名称\superpart
。不妨自命不凡地称之为“Book”?
\NewDocumentCommand{\superpartname}{}{Book}
最后,我们创建了一个钩子,用于在页面标题中使用 superpart 标题(如果我们选择的话)。我决定让它执行该操作\part
,即在两个标记中都放入空文本。
\NewDocumentCommand{\superpartmark}{m}{\markboth{}{}}
这就是(模数拼写错误,因为这当然都是未经测试的)如何从头开始定义分段命令。
编辑Ulrike Fischer 指出,需要付出一些额外的努力才能使分层书签发挥hyperref
作用。⁴hyperref
假设我们使用 LaTeX 的内部宏(和宏结构)来完成其工作。以下是它的作用\part
:
\let\H@old@part\@part % ❿
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname chapter\endcsname\relax
\let\Hy@secnum@part\z@
\else
\let\Hy@secnum@part\m@ne
\fi
\def\@part{%
\ifnum\Hy@secnum@part>\c@secnumdepth
\phantomsection % ⓫
\fi
\H@old@part
}
% \end{macrocode}
% \begin{macrocode}
\let\H@old@spart\@spart % ❿
\def\@spart#1{%
\Hy@MakeCurrentHrefAuto{part*}% ⓬
\Hy@raisedlink{%
\hyper@anchorstart{\@currentHref}\hyper@anchorend
}%
\H@old@spart{#1}%
}
在 ❿(出现两次)处,我们使用了一个修补宏的老派技巧:(\let\foo=\bar
是=
可选的)将 的当前含义复制\bar
到 中\foo
。当我们想要重新定义\bar
但保留其功能时,这很方便。例如
\let\foo\bar
\NewDocumentCommand{\bar}{%
stuff before old bar
\foo % old bar functionality
stuff after old bar
}
现在孩子们都在使用patchcmd
软件包或ted
进行更改,这更为可靠,但无论如何,这些修改都假设我们对命令定义方式的内部原理有所了解。无论如何,hyperref
对我们的命令一无所知\superpart
,所以它什么也不会做。
⓫ 是我们的目的中最重要的部分。\phantomsection
在出现的位置添加一个锚点。文档表明它应该在 旁边\addcontentsline
,所以我们必须回到我们的文档并\phantomsection
在我标记 ➀ 的行后插入,但我们不想直接插入它,因为它可能不存在!所以我们改为这样做
\ifdefined\phantomsection
\phantomsection
\fi
在那一点。那么 ⓬ 处的代码呢?好吧,事实证明,这几乎与 的代码完全相同\phantomsection
,唯一的区别是而不是。我们在非 的情况下使用 的事实\phantomsection
表明该值是什么并不重要,因此我们可以在选择的点处获得一个。\Hy@MakeCurrentHrefAuto{section*}
\Hy@MakeCurrentHrefAuto{part*}
\phantomsection
*
\phantomsection
为了处理层次结构,还有一件事是必要的hyperref
。我们需要
\NewDocumentCommand{\toclevel@superpart}{}{-2}}
这些\toclevel@*
命令不是 LaTeX 内核的一部分,但被类等使用,ams*
并且也hyperref
利用了这一点。如果我们没有为分段级别定义级别,hyperref
则默认为 0(相当于\chapter
in book
),这不是我们想要的。再说一次,我没有测试过这些,但我认为我已经把所有移动部件都准备好了,或者至少解释得足够好,你应该能够修复任何错误。
关于这一点我有点撒谎。这与默认的 LaTeX 分段命令定义之间有一个关键区别:此定义允许您写入
\superpart*[foo]{bar}
哪个,默认情况下 LaTeX 将被解释为\superpart*{[} foo]{bar}
哪个foo]{bar}
将是 之后的第一个段落\superpart*
。(顺便说一下,文档中提到了这一点xparse
,尽管更简洁一些。)印刷师用花哨的语言来表示右侧。左侧称为 verso。
不适用的情况是双栏模式下的after
\part
和 after 。我认为这些都是疏忽,但 37 年后再改变可能已经太迟了。\chapter
book.cls
他还发现了一些拼写错误,我已经修正了。谢谢你的校对!
答案2
类(和memoir
的超集)在分区上方提供了一个分区。手册提供了有关此代码的一般详细信息。和的格式的各个方面都很容易配置。book
report
\book
\part
\book
\part