最近因为课程作业的原因,不得以提前准备毕业论文的 LaTeX 模板。作为一个仅使用过 LaTeX 而未制作过模板的人来说,这其实挑战还挺大的。不如从 WHU-Thesis1(以下简称为whu) 开始魔改一份模板出来。
那么,WHU-Thesis 做了什么?
创建 Logger
首先 whu 为 \msg_new
等函数创建了一个别名
其中这里由于 LaTeX 顺序展开的原因,可以做到类似柯里化的机制。
对于 \cs_new:Npn \__whu_msg_new:nn { \msg_new:nnn { whu-thesis } }
来说,它的完整定义应该是这样
这代表着定义了一个新函数 \__whu_msg_new:nn
,它接受两个参数,分别是消息的唯一名称和实际输出的消息。当调用此消息时将创建一个新的输出函数,该函数以 whu-thesis
为分类名进行输出
提供兼容方案
检查 \NewDocumentCommand
是否存在。如果它不存在,那么执行 { \RequirePackage { xparse } }
,即要求加载 xparse
包
上述语句中分别通过 \__whu_msg_new:nn
创建两条输出属于 unsupported-engine
和 l3-to-old
。接下来先检查 expl3
, xtemplate
和 l3keys2e
的包发行时期是否在 2018/05/12
之前,如果在此之前则调用 l3-to-old
进行输出。同理,如果引擎不支持则调用 unsupported-engine
进行输出。
为用户提供初始化命令
在下面的语句中定义了 whu/style
和 whu/info
两个元键值对。
这种写法基本相当于:
感觉有点废话?但是实际上上面的代码是不能运行的。因为上面的代码缺少 whu/style
和 whu/info
的定义。但对于最初的代码来说则是可执行的,因为他的定义和赋值在同时发生
定义全局变量
不必多言
?
不知道在干什么
似乎是在文档开始前去调用 xeCJK
创建函数变体
基本函数
空白页
__whu_new_blank_page
创建一个新页面,并将页面为空白页样式。这意味着当前页面上不会显示页眉、页脚或页码,整个页面将是空白的
分散盒子
\__whu_spread_box
创建分散盒子:先创建一个水平盒子,再对于 #2
中的内容的每两个元素之间添加一个弹性填空(\hfil
)
\__whu_spread_box_with_end_spaces
同理,只是在最后重新添加了 0.19cm
的空白
带圈数字
为用户创建 circlenumber
命令,可创建带圈数字。如果第一个参数为 true 则使用 tikz 创建;否则使用 Unicode
tikz 画图硬汉
获取宽度与-clist-的内容的最大宽度
\__whu_get_text_width
通过设置hbox
的内容为 #2
获取其宽度并存储在 #1
中
\__whu_get_max_text_width:NN
将列表#2
的内容依次弹出,然后通过 \__whu_get_text_width
获取其大小并比较,最后将最大的宽度存储在 #1
中
删除章标题中的-\quad
\__whu_sanitize_chapter_title
将 token list #1
中的 \quad 全部移除
这是一个相当有技巧性的写法。通过将 #1
记 tl 类型并通过 \tl_remove_all
操作删除其中所有的 \quad
。
不过要注意这样删除之后的输出在 \l__whu_tmpa_tl
变量中
手动生成章的标题,用于摘要、参考文献等
对于 \__whu_chapter_header
,它判断是否设置了 \g__whu_twoside_bool
变量,如果设置了则将左右页眉都设为 #1
; 否则则设置单个页眉,并通过两个 \hfill
居中显示
再来说 \\__whu_chapter
,它首先在该作用域中关闭了自动编号,接着创建了 #1
章节,并通过删去 \quad
的 #1
作为目录页的索引。最后通过调用 \__whu_chapter_header
创建页眉
处理文档类选项
定义选项
一些中规中矩却又容易出错的常量设置
值得一提的是此处将所有配置都传给了 ctexbook
包,包括:
- 字号 zhihao
- 行距倍数 linespread 2
- 编码
- 字体集
- 外部配置
g__whu_to_ctexbook_clist
对于行距倍数,这里通过 \dim_radion:nn
进行了单位换算。以本科为例:当字号为小四(12pt)时,23磅间距是指 23pt / 12pb
倍
对于 ctexbook,它的 layout3 是这样的:
给预加载的宏包传递选项
消去 CJK 警告
在包执行结束后进行消息重定向,以达到丢弃消息的目的
加载包
页面尺寸设置
处理图书馆版本选项
如果启用了 library
选项,则在接下来的代码中用 \clearpage
取代 \cleardoublepage
。
\cleardouble
和 \clearpage
在大部分时间是一致的,但 \cleardoublepage
同时还会检查页码。如果当前的页码是奇数并且 typesettings 是 twosided
时,\cleardoublepage
还会再多插入一页,使新的一页仍是奇数页4。如果启用了 library
选项,则不会再新插入一页
字体配置
字体配置预备函数
提供了
\__whu_set_cjk_main_font:nn
\__whu_set_cjk_sans_font:nn
\__whu_set_cjk_mono_font:nn
\__whu_set_cjk_font_kaishu:nn
用于设置字体
字体配置项
在 whu/style
中添加了多个与字体相关的项,在设置该项时会调阅前面的配置语句
西文字体配置预备函数
提供
\__whu_style_font_set_times
\__whu_style_font_set_xits
\__whu_style_font_set_terms
用于设置西文字体
数学字体预备函数
中文字体预备函数
提供设置中文字体的方法
\__whu_style_cjk_font_set_none
\__whu_style_cjk_font_set_windows
\__whu_style_cjk_font_set_mac
\__whu_style_cjk_font_set_fandol
\__whu_style_cjk_font_set_founder
\__whu_style_cjk_font_set_sourcehan
使用字体5
在 preamble 的最后(\documentclass
命令和 \begin{document}
命令之间)添加字体使用语句
当 \g__whu_style_math_font_choice_tl
为 default
时使用 Ralph Smith's Formal Script
字体。接下来声明了一个名为 rsfs
的字体族(font family),并设置了其 skew 字符(倾斜字符)为 127。这个设置可以确保字体在倾斜时不会出现问题。
\DeclareFontShape{U}{rsfs}{m}{n}{...}
:这行命令用于声明字体的形状(font shape),这里的 U
表示使用 Unicode 编码,rsfs
是字体族名称,m
表示字体系列(font series),n
表示字体形状(font shape)。
在大括号内的 <5-6> rsfs5
、<6-8> rsfs7
和 <8-> rsfs10
分别表示字体大小的范围和对应的字体文件。它们表示:
- 对于字体大小在 5pt 到 6pt 之间的情况,使用
rsfs5
字体文件;
- 对于字体大小在 6pt 到 8pt 之间的情况,使用
rsfs7
字体文件;
- 对于字体大小大于等于 8pt 的情况,使用
rsfs10
字体文件。
章节标题设置与列表设置
移除列表垂直间距
设置列表(enumerate
、itemize
和 description
环境)的垂直间距为零
配置 ctex
创建不同的函数用于适配不同的用途,主要包含以下属性:
Key | Desc |
---|
chapter/numbering | 章节编号 |
chapter/format | 章节标题格式 |
chapter/number | 章编号内容,例如阿拉伯数字、罗马数字等 |
chapter/numberformat | 章编号格式 |
chapter/beforeskip | 章节标题之前的垂直间距,设置为负数即向上移动 |
chapter/afterskip | 章节标题之后的垂直间距。 5ex plus 1ex minus 1ex 意为5 行高,最多扩展 1 行高,最少减少 1 行高 |
chapter/pagestyle | 章节页眉页脚样式设置为空白 |
chapter/titleformat | 章节标题的格式 |
chapter/fixskip | 调整章标题前后的垂直间距 |
对于 section
、subsection
、subsubsection
等同理
作者分别通过下列函数进行设置
Name | Desc |
---|
\__whu_proposal_report_set_ctex_format | 开题报告 |
\__whu_proposal_tasks_set_ctex_format | 本科毕业论文(设计)任务书 |
\__whu_bachelor_set_ctex_format | 本科 |
\__whu_master_set_ctex_format | 硕士 |
\__whu_doctor_set_ctex_format | 博士 |
除此之外还通过 \setenumerate
设置了列表项样式
Key | Desc |
---|
labelindent | 标签缩进 |
leftmargin | 左侧边距 |
widest | 最宽项 |
itemindent | 项目缩进设置 |
listparindent | 段落缩进量 |
label | 标签格式设置(如罗马数字) |
Name | Desc |
---|
\__whu_bachelor_set_enumerate_format | 本科列表样式 |
\__whu_master_set_enumerate_format | 硕士列表样式 |
\__whu_doctor_set_enumerate_format | 博士列表样式 |
判断论文种类
首先对本科、硕士和博士论文分别进行样式设置。然后创建了两个命令,分别是 \ProposalTasks
和 \ProposalReport
。这两个命令接受一个参数,并具有一个默认值。在命令的实现中首先设置了相关样式,接着以传递参数创建了一个章节,并在之后重置了计数器 \c@section
。这样新的章节开始后,下一个节的编号将从 1 开始。
页眉页脚样式
其中 \fancyhf
用于清除当前的页眉页脚设置,然后调用 \fancyhead
设置页眉也页脚。在页眉和页脚的设置中,C
表示居中,类似的有 L
和 R
。E
和 O
表示 even 和 odd
在最后使用 \AddToHook
在 cmd/mainmatter/after
之后执行 \pagestyle
设置相关样式,其目的是统一后记 (backmatter) 的样式与 mainmatter
个人信息配置项
值的一提的是这里会将公共常量定义为c__whu_name_#1_tl
,例如 \c_whu_name_author_tl
对应 姓名
根据 \g__whu_thesis_type_int
不同,调用的命令来初始化常量
落款
以 ProposalReportSignature
为例
即将签名放到页面最下放
中文封面
本科
本科论文的封面由 logo, title, info, date 组成。
封面使用的边距不同于内容,此处通过 \newgeometry
调整了外边距,并在结束处使用 \restoregeometry
恢复
硕士
博士
博士封面与硕士封面的布局一样,唯一的区别就是 logo 下方的论文类型,
一个是“博士学位论文”,一个是“硕士学位论文”
英文封面
本科
这边的个人信息部分竟然是表格 :)
不太明白这里为什么要用 tikzpicture
环境,WHU 这么干一定有它的道理
硕士
博士
原创声明
本科原创性声明
本科版权使用授权书
4.653cm 是用尺子量出来的吗
硕士原创声明
博士原创性声明
博士使用授权协议书
博士论文创新点
这里重设了 ctex 的 chapter ,使之居中对齐并取消页眉页脚
之后判断文件 pages/innovation.tex
是否存在,如果存在则导入此文件
摘要和关键词
这个位置关于 \l__whu_abstract_keywords_en_type_str
取默认值的方法相当精彩。
在 key 定义时不配置默认值,而是在 Preamble 的结束部分进行判断。按照标准,如果在这时候该值仍未配设置,则以后也不会更新,那么这时就可以将 \l__whu_abstract_keywords_zh_type_str
赋值到 \l__whu_abstract_keywords_en_type_str
本科
这里还能水个 pr
硕士
博士
输出封面及摘要
目录
统一目录标题和正文标题
使 \chapter
、\section
等命令吞参数,即不能输入 \chapter[]{}
而只能输入 \chapter{}
。
这里使用了 \RenewDocumentCommend
命令来重新创建这几个参数,在其中如果 #2
不为空,则给出一段 warning
上述语句被定义在 \__whu_bachelor_chapter_cmds_no_optional_argument:
中,只有当 \g__whu_thesis_type_int
为 2 时才会启用
本科设置
硕士设置
博士设置
输出配置
重定义目录
首先配置目录的 chapter 应当是居中的(注意不是目录内容中的 chapter,而是目录两个字),且该页的页眉页脚应当是 frontmatter 的样式。配置结束后调用旧的 \tableofcontents
插图目录和表格目录
致谢环境
添加了 acknowledgements
环境,这样的话可以直接这样使用该环境
附录
修改附录中编号为 \thechater \arabic{equation}
。这样做的效果是,每个数学公式的编号前面会加上章节编号,以区分不同章节中的公式。
并设置附录的章节编号格式设置为了大写字母表示的章节编号
脚注
\cs_set:Npn \thefootnote {\whu_footnote_number:N}
重新定义了脚注的编号格式。默认情况下,LaTeX 中脚注的编号是阿拉伯数字,但这里通过 \cs_set:Npn
命令将其重新定义为调用 \whu_footnote_number:N
函数,并传递当前脚注计数器的值。
在\whu_fontnote_number
中会对 \l__whu_fn_style_tl
的值进行判断,并依据其 token list 的值生成对应的数字
\cs_set:Npn \@makefntext
设置了脚注文本的格式的命令 \@makefntext
。其保证了:
\mode_leave_vertical:
: 垂直模式处于结束状态
\hbox_to_wd:nn {1 em} {\@thefnmark \hfil}
: 创建了水平 1em
的盒子用于容纳脚注标记
\zihao{5}
字号
#1
脚注内容
\cs_set:Npn \footnoterule
重新定义了 LaTeX 中用于绘制脚注分隔线的命令
\kern-3\p@
:这个命令在竖直方向上向上移动 3pt 的距离。3\p@
表示 3pt,负号表示向上移动。
\hrule
:这个命令用于绘制一条水平线。
@width 2in
:这个命令指定水平线的宽度为 2in(英寸)。
@height 1pt
:这个命令指定水平线的高度为 1pt(点)。
\kern 2.6\p@
:这个命令在竖直方向上向下移动 2.6pt 的距离。2.6\p@
表示 2.6pt,正号表示向下移动。
这段代码的效果是绘制一个宽度为 2in、高度为 1pt 的水平线,该线的顶部边缘与脚注文本底部略微重叠,与页面底部有一定的间距。
符号表
此处创建了一个 notation
环境,这种操作和上面的致谢环境很类似。
在 notation 环境中,会先创建一个居中不带标号且有frontmatter样式页眉的章节,内容为第一个参数(默认是“符号表”),然后创建一个居中的表格,其内容为第二个参数。
这也意味着在这个环境中,需要用 tabular 环境中的语言来进行书写
比如说官方示例给出的用法:
图表
图
改个字体先
\DeclareCaptionFont
是 LaTeX 中用于声明和设置图表标题字体的命令。它允许用户自定义图表标题的字体样式,比如字体族、字体大小、字体颜色等。
通常,\DeclareCaptionFont
命令被用于在 LaTeX 文档中使用 caption
宏包时设置图表标题的字体。该命令允许用户指定多种不同的字体样式,并且可以为不同的图表类型设置不同的字体样式。
这里通过这种方式设置了 figure,table和 tabular 的字体样式
定理环境
\declaretheoremstyle
是用于声明定理环境样式的命令。在这个例子中,一个名为 whustyle
的定理样式被声明。
headpunct = {}
表示定理标题和定理内容之间的标点为空。
postheadspace = {0.5em}
表示在定理标题和定理内容之间添加 0.5em 的额外空间。
headindent = 2\ccwd
表示定理标题的缩进量为 2 个“当前字宽”的长度。
接下来通过 \clist_map_function:nN
依次将不同环境的标题参数传入 \__whu_declare_theorem_with_counter_within
来创建对应的定理环境。
不过我没看到 \__whu_declare_theorem_with_counter_sibling
在哪里用到了
\RenewDocumentEnvironment { proof } { O{\proofname} +b }
: 这一行声明了一个名为 proof
的环境,并接受两个参数。第一个参数是可选的,用于指定证明环境的名称,默认值为 \proofname
(通常是“证明”)。第二个参数是必选的,用于指定证明环境的内容。
- 在环境的开头部分,进行了一些设置:
\par
:开始新的段落。
\pushQED{\qed}
:将证明环境的结束标志(通常是一个小方块,表示证明结束)推入证明结束的队列中,以便在证明结束时自动添加。
\normalfont
:设置字体为正常字体。
\topsep6\p@\@plus6\p@\relax
:设置顶部间距为 6pt,允许额外的 6pt 弹性间距。
\trivlist
:开始一个列表环境。
\item\relax
:开始一个新的项,并使用 \relax
避免出现意外的空白。
\group_begin:
:开始一个分组,用于限制样式设置的作用范围。
\hspace*{2\ccwd}
:插入一个长度为 2 个当前字符宽度的水平空白,用于缩进证明环境的标题。
\bfseries #1\@addpunct{:}
:设置证明环境的标题为加粗字体,标题内容为参数 1(即\proofname
或者自定义的标题),并加上一个冒号。
\group_end:
:结束分组。
\hspace\labelsep
:插入一个标签和文本之间的空白距离。
\ignorespaces
:忽略环境开始时可能存在的空格。
- 在环境的结束部分,进行了一些清理工作:
\popQED
:弹出证明结束的标志,以便在证明环境结束时不再添加。
\endtrivlist
:结束列表环境。
\@endpefalse
:确保不在环境结束时在段落后插入额外的垂直空白。
效果:
钩子管理
和 上面的 一样,看不懂 :(
参考文献
bibtex