目录:

宏语言

就像那些上古的语言——bash, commandline之类一样,TeX是宏语言。 简单地说,宏语言就是完全依赖字符串匹配执行任务的语言。 (如果对此理解困难,想想C++的#define#ifdef之类。)

宏语言为何不受欢迎?

Donald Knuth 所开发的 TeX 系统,其排版原语只有 300 多个,但是通过 TeX 宏可以将这些排版原语组合起来,从而完成更为复杂的排版任务。对于这种任务,宏语言的运行效率要高于一种通用的编程语言。对于 Knuth 而言,这一决策是正确的,因为这样的 TeX 完全满足了他的需求。后来随着排版任务的复杂化,宏的局限性就日益的呈现了出来。如果始终坚持用宏的方式来扩展 TeX 的功能,进度是缓慢的,参与者的数量是逐步减少的,而且这一切都依赖于底层不能发生任何变化。这种系统迟早会变成恐龙的。Knuth 的 TeX 只支持 8 位字符,后来要让它支持中文,Hacker 们不得不绞尽脑汁的在宏包的层面上去做工作,以至于如何让 TeX 支持中文,对于中文用户而言,长期以来一直是初学者遇到的第一个本来不应该是障碍的障碍。

LaTeX对TeX做了包装,使其尽可能像现今流行的编程语言——包括明确的函数作用域、可选参数之类,但其底层依然脱离不了宏语言的实质。 所幸这种麻烦大多只在编写宏包时遇到,作为初学者大约不用在意这么多(也因此我颇觉得,LaTeX应该支持Python中间层用来编写宏包qwq)。 以下列举对初学者而言,宏语言导致的坑点。

作为函数参数的中括号不能嵌套

TeX对大括号做了特别处理,使其可以嵌套;但是LaTeX并没有对中括号作同样的处理。因而函数的中括号定位是基于字符串匹配的!它只会向右找到第一个右中括号,然后配对。因此以下写法报错(只是举例):

\section[\cite[def]{ghi}]{abc}

为了得到正确结果,我们需要用大括号屏蔽内层函数,也就是如下写法:

\section[{\cite[def]{ghi}}]{abc}

数值计算

如你所见,宏对文本非常友好。但是,不妨思考如下问题:如何只用字符串匹配完成10进制数的乘除法呢?对于排版和绘图而言,这是再常用不过的功能。(比如0.8\textwidth和绘图里面各种算出来的位置/长度。)

反正这个坑我也不知道怎么办……

文档

所有文档都可以在这里找到:CTAN: Comprehensive TeX Archive Network 如果下载的是完整的TEX发行版,那么你应该可以在本地看到这些文档。在VS Code下,这需要将鼠标悬浮在需要的包上(例如,\usepackage{cleveref}中的cleveref),在弹出的提示框内点击View Document即可。

已知例外是,TiKZ包的文档在pgf下。

Shebang

暂且记录于此。可以选择性使用。

% !TEX encoding = UTF-8
% !TEX program = latexmk
% % !TEX root = somefile.tex
% !BIB program = biber % or bibtex

常用宏包(转载)

转载自:孟晨的知乎回答

常见的宏包推荐。

首先是国外用户写的一篇文档。(链接已失效。)

有翻译:(原始链接已失效,此处为两个存档)

接下来……

中文支持。

  • ctex - 封装好的中文支持和版式调整工具,定义了许多方便的工具
  • xeCJK - XeLaTeX 下的中文字体选择和禁则、压缩的处理
  • fontspec - XeLaTeX 下的西文字体选择

页面布局类。

  • geometry - 调整页面大小、页边距等尺寸
  • fancyhdr - 设计页眉页脚
  • titlesec - 设计章节标题格式
  • titletoc - 设计目录格式

超链接和 PDF 的各种功能。

  • hyperref - 超链接,PDF 书签,PDF 表单,PDF 元信息……
  • media9 - 插入 Flash、视频等

图表和浮动体。

  • graphicx - 插图
  • xcolor - 颜色
  • tikz - 绘图
  • booktabs - 三线表
  • multirow - 列合并单元格(cell)
  • makecell - 在单元格内手动换行
  • longtable - 换页表格
  • tabu - 封装了各种接口的表格宏包,制表强烈推荐
  • threeparttable - 在表格中使用脚标,和 tabu 有冲突。
  • diagbox - 斜线表头(作者:知乎@刘海洋)
  • float - 提供了 H 选项,禁止浮动体浮动(除非必要,不建议这么干)
  • placeins - 提供了\FloatBarrier命令,限制浮动体浮动范围

列表环境。

  • enumitem - 修改列表环境的各种间距、label 样式等的不二法门

其他一些工具。

  • nag - 检查你是否使用了过时的宏包和命令的宏包
  • etoolbox - 主要是针对宏包和文档类开发者,不过提供了一些对环境的钩子,有时候很有用
  • xpatch - 修补命令用的
  • environ - 增强了 LaTeX 本来的\newenvironment的功能,解决了一些花括号不匹配导致的问题

暂时想到这么些,回头再补充吧……

引用

  • 可以使用宏包cleveref,调用命令为\Cref\cref,可以自动填充引用对象(比如可以显示Theorem 1.1而非1.1)。
  • 可以使用如下命令来使cleveref总是使用首字母大写格式:

    \usepackage[capitalize]{cleveref}
    
  • 宏包showkeys用来在引用对象附近注明引用标签。notref选项用来关闭在\ref\Cref等命令附近的标签。final模式下宏包showkeys自动被禁用。宏包用法如下:

    \usepackage[notref,notcite]{showkeys} % 文档格式为final时自动禁用
    
  • 这条没有考证:据说hyperref要在cleveref前导入。
  • 我们使用~来输出不能断行的空格。一般引用中的页码“p. 123”或者“引理 1.1”中间的空格不断行,因此建议使用命令p.~123引理~1.1

biblatex

  • biblatex包下常用的引用格式参见这里.

子图、子表格

我们使用如下命令以引用子图:(默认引用Figure 1a

\usepackage{subcaption}

如果我们想让子图引用为Figure 1(a),则应采取以下写法:

\usepackage[labelformat=simple]{subcaption}
\renewcommand\thesubfigure{(\alph{subfigure})}
\renewcommand\thesubtable{(\alph{subtable})}

改变enumerate的枚举格式

\renewcommand{\labelenumi}{(\arabic{enumi}).}

编号

在节内编号

\numberwithin{equation}{section}
\numberwithin{figure}{section}
\numberwithin{table}{section}

让图片、表格和算法共享编号。

\makeatletter
\let\c@table\c@figure
\let\c@algorithm\c@figure
\makeatother

中文显示

  • 选项scheme=plain用来在支持中文的同时不改变文档原格式(比如显示“Section”而非“节”,首页显示英文日期而非中文日期,等等)。用法:

    \usepackage[scheme=plain]{ctex}
    

草稿模式

  • 选项finaldraft用来控制是在草稿模式还是终稿模式。草稿模式下,如果某一行过长会有黑框。
  • 如上所述,final模式下宏包showkeys自动被禁用。

定义草稿模式下的额外行为

草稿模式较其他模式唯一的区别为:草稿模式下\overfullrule大于0(作用是,在行末溢出处加个黑框提示溢出)。 因此可以通过检测\overfullrule的值判断是否在草稿模式。

参考网页。

% 定义在draft模式下的额外行为
\makeatletter
\def\ifdraft{\ifdim\overfullrule>\z@
  \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
\makeatother
% 如果在草稿模式下,那么每节前分页,以节省打印纸张。
\ifdraft{\pretocmd{\section}{\clearpage}{}{}}{}

如果写包的话,问题简单得多:draft将会作为选项传递给包。因此直接检测选项即可。

文档样式

  • 如下命令可以禁用底部页码。

    \pagestyle{plain}
    
  • 如下命令以手动调整页面大小。

    \special{papersize=148mm,210mm} % A5 paper size.
    

改变页边距

  • 使用宏包的方法:

    \usepackage{geometry}
    \geometry{a4paper,scale=0.8}
    
  • 不使用宏包的方法:

    \addtolength{\oddsidemargin}{-.875in}
    \addtolength{\evensidemargin}{-.875in}
    \addtolength{\textwidth}{1.75in}
    \addtolength{\topmargin}{-.875in}
    \addtolength{\textheight}{1.75in}
    
  • 当时寻找下面一种不使用宏包的方法,是因为机械硬盘下宏包geometry导入似乎很慢。固态硬盘下看起来问题不大。(别问我为什么编译依然这么慢,我不知道。)

数学公式

字符间距

  • 建议使用\lvert\rvert作为左右|符号,以保证正确间距。
  • \bigl, \bigm, \bigr, \big效果几乎一样,但是其作用后的符号类型分别为\mathopen, \mathrel, \mathclose, \mathord.
  • 十分不幸, $\TeX$ 中可以正确处理双目运算符和左结合单目运算符,但是无法正常处理右结合单目运算符(思考:n! r!)。这是 $\TeX$ 的锅,我们为了正常显示,只能在!后加上 $\frac{3}{18}$ em 的空格,即\,

手动标号

经常遇见的情况是,一长串公式只有一个想要标号,因此不想每行加个\nonumber。能不能造个相反功能的\numberthis? (比如说,用来在align*环境中加入tag) 以下给出两种方案:(我的导言区采用了第一种)

  • \newcommand{\numberthis}{\refstepcounter{equation}\tag{\theequation}}
  • \newcommand{\numberthis}{\addtocounter{equation}{1}\tag{\theequation}}

字体选择

字体简介

LaTeX字体分为三个维度: family, shape, series. 通常而言, 同一个维度只能选择一种字体, 不同维度的字体可以任意组合.

  • family字体族: \rmfamily, \sffamify, \ttfamily.
  • series字体族: \mdseries, \bfseries, \lfseries.
  • shape 字体族: \upshape, \itshape, \slshape, \scshape.

这些命令的含义请参见wikibook. 这些命令的作用域是自命令位置起的全局, 有时候我们只需要使其作用于部分位置, 当如下使用:

{\rmfamily This is sample text.}

或者, 取首两个字母, 前缀textmath构成单参数命令, 使被作用参数变成指定字体, 形如\textrm{some text here}\mathit{some text here}. 如只需采用默认字体, 亦可单使用\text{some text here}\textnormal{some text here}.

字体大小

字体从小到大依次为:

  • \tiny
  • \scriptsize
  • \footnotesize
  • \small
  • \normalsize
  • \large
  • \Large
  • \LARGE
  • \huge
  • \Huge

使用方式为 (以下二者效果相同):

  • {\large abcd}
    
  • \begin{large}
        abcd
    \end{large}
    

参考字体

在选择合适字体时, 如下图片可供参考: 字体选择参考

证明中分情况讨论

证明中分情况讨论,可能还需要引用,但是似乎amsthm却缺少相应环境……怎么办? ——自己动手丰衣足食嘛~

这是(默认环境的参数)[https://tex.stackexchange.com/questions/17551/amsthm-what-are-the-newtheoremstyle-parameters-for-the-default-styles]。

仿照之,可以魔改出Case的参数,如以下代码。 随后使用\renewcommand{\thecase}{\arabic{case}}修改默认显示(引用)方法。

我的最终代码如下:

% Case in proof
\newtheoremstyle{ModifiedRemark}
    {0.5\topsep}             % ABOVE SPACE
    {0.5\topsep}             % BELOW SPACE
    {\normalfont}            % BODY FONT
    {0pt}                    % INDENT (empty value is the same as 0pt)
    {\scshape}               % HEAD FONT % Different from Environment"remark"
    {.}                      % HEAD PUNCT
    {5pt plus 1pt minus 1pt} % HEAD SPACE
    {}                       % CUSTOM-HEAD-SPEC
\theoremstyle{ModifiedRemark}
\newtheorem{case}{Case}[theorem]
\renewcommand{\thecase}{\arabic{case}}
\crefname{case}{Case}{Cases} % 告诉cleveref如何引用case环境

我的导言区代码(已弃用)

附上我的导言区文件:

\documentclass[a4paper,10pt]{article}
\usepackage{amsmath,amsthm,amssymb,mathtools} % Basic Packages % amssymb依赖amsfonts
\usepackage{regexpatch} % 替代etoolbox提供各种钩子。本导言区中用到的是\pretocmd。

% Fonts
% \usepackage{mathrsfs} % 花体 \mathscr
% \usepackage{bbm}      % 空心体 \mathbbm
% \usepackage{dsfont}   % 空心体 \mathds

% Change margin
% \pagestyle{plain} % 文档样式; empty则底部不放置页码.
% \special{papersize=148mm,210mm} % A5 paper size. % 如果需要手动调整页面大小
\usepackage{geometry}
\geometry{a4paper,scale=0.8}

% Graph
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{positioning}
% \usepackage{graphicx}   % 支持插入图片
% 支持子图,引用为Figure 1(a)
\usepackage[labelformat=simple]{subcaption}
\renewcommand\thesubfigure{(\alph{subfigure})}
\renewcommand\thesubtable{(\alph{subtable})}

% Label, Link
\usepackage[style=alphabetic,sorting=none,isbn=false]{biblatex} % numeric, authoryear.
% \addbibresource{./put/bib/file/here.bib}
\ExecuteBibliographyOptions
{
    maxcitenames=3, maxbibnames=100, minnames=3,
}
\AtEveryBibitem{
    \clearfield{issn}
}
\usepackage[colorlinks]{hyperref}
\usepackage[capitalize]{cleveref}
\usepackage[notref,notcite]{showkeys} % 文档格式为final时自动禁用
\usepackage{url}

% Other packages
% \usepackage{ifthen} % 支持条件判断
% \usepackage[toc,page]{appendix} % 支持附录
% \usepackage[scheme=plain]{ctex} % 支持中文

\makeatletter
\def\ifdraft{\ifdim\overfullrule>\z@ % 定义在draft模式下的额外行为
    \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}
\makeatother
% \ifdraft{\pretocmd{\section}{\clearpage}{}{\GenericWarning{Error when prepending to command \backslash section}}}{} % 如果在草稿模式下,那么每节前分页,以节省打印纸张。
\newcommand{\ProofStyle}[2][\square]{
    \cspreto{#2}{\pushQED{\qed}\renewcommand{\qedsymbol}{\ensuremath{#1}}}
    \cspreto{end#2}{\popQED}
}

% % 编号
% \numberwithin{equation}{section}
% \numberwithin{figure}{section}
% \numberwithin{table}{section}
% \renewcommand{\labelenumi}{(\arabic{enumi}).}
% % 让图片、表格、算法共享编号。
% \makeatletter
% \let\c@table\c@figure
% \let\c@algorithm\c@figure
% \makeatother

% Environments
\newtheoremstyle{ModifiedRemark}
    {0.5\topsep}             % ABOVE SPACE
    {0.5\topsep}             % BELOW SPACE
    {\normalfont}            % BODY FONT
    {0pt}                    % INDENT (empty value is the same as 0pt)
    {\scshape}               % HEAD FONT % Different from Environment{remark}
    {.}                      % HEAD PUNCT
    {5pt plus 1pt minus 1pt} % HEAD SPACE
    {}                       % CUSTOM-HEAD-SPEC
\theoremstyle{plain}
\newtheorem{theorem}{Theorem}[section]
\newtheorem{proposition}[theorem]{Proposition}
\newtheorem{corollary}[theorem]{Corollary}
\newtheorem{lemma}[theorem]{Lemma}
\newtheorem{conjecture}[theorem]{Conjecture}
\newtheorem{question}[theorem]{Question}
\theoremstyle{definition}
\newtheorem{definition}[theorem]{Definition}
\theoremstyle{remark}
\newtheorem{example}[theorem]{Example}
\newtheorem{remark}[theorem]{Remark}
\ProofStyle[\Diamond]{example}
\ProofStyle[\Diamond]{remark}
\theoremstyle{ModifiedRemark}
\newtheorem{case}{Case}[theorem]
\newtheorem{claim}[case]{Claim}
% 告诉cleveref如何引用环境
\renewcommand{\thecase}{\arabic{case}}
\crefname{conjecture}{Conjecture}{Conjectures}
\crefname{example}{Example}{Examples}
\crefname{case}{Case}{Cases}
\crefname{claim}{Claim}{Claims}

% 从我导师的preamable template中继承的. % 我并不知道其效果。
% \newcommand{\OEIS}[1]{\href{http://oeis.org/#1}{\nolinkurl{#1}}}
% \newcommand{\doi}[1]{\textsc{doi}: \href{http://dx.doi.org/#1}{\nolinkurl{#1}}}

% New commands
\newcommand{\email}[1]{\href{mailto:#1}{\nolinkurl{#1}}}
\newcommand{\keywords}{\par\bigskip\noindent\textbf{Keywords: }} % 用来在摘要里加上keywords
\newcommand{\eqgap}{\mathrel{\phantom{=}}} % 在align环境中对齐使用 % 等于一个等号的间距
\newcommand{\numberthis}{\refstepcounter{equation}\tag{\theequation}} % 用来在align*加入tag

\begin{document}

\end{document}