-->

Latex fundamental 知识点

Posted on By Marquis

空格

一行中的连续空格等同于一个空格
数学公式中的空格等同于没有空格

行首的空格会被忽略

一个空行标志一段的结束
多个空行等同于一个空行

Tex中的所有字符都要当做一个command,即使是一个最简单的字符如’a’,也是a command to typeset an `a’.

control sequences有两类

  1. \+一个或多个字母,这种的话遇到非字母就命令的名字就结束了
  2. \+一个非字母的字符,如\$

一个control word会自动吸收后边的空格,破解方法:
\TeX\ \TeX{} 或 {\TeX}

Tex对于标点后边一般会自动加个额外的空格,如果不想要这个空格,咱们就在后边自己加\ ,如 Proc.\ Royal Acad.\ of Twits
如果标点的前面有字母,tex就不加空格了,如果我们想要空格,就可以自己加: A computer from IBM\null?,这个\null就把字母M和问号分离了。 (这是因为句号前面如果是大写字母的话,tex认为这个句子还没有结束,不会加额外的空格 如果想主动结束可以这么搞 DNA\null)

expandafter

Tex for the impatient的笔记中,我们已经了解了\expandafter的基本用法,下面根据另一篇文章A Tutorial on \expandagter (TUGboat 1988年的文章),来深入探讨一下其用法,主要是摘抄几个核心的例子。

简单的展开例子

\def\xx{\yy}
\expandafter\def\xx{This is fun}

那么执行到第二行的时候,Tex会将\def这个token先暂存起来不理它,然后展开\xx,得到\yy,因此这个例子等价于:\def\yy{This is fun}

例子

\expandafter ab
此时,先将字符a暂存,然后展开b,由于b没法展开,因此这俩字符还是按照原来的顺序打印出来。
这个例子告诉我们:\expandafter只能颠倒展开的顺序,不能颠倒执行的顺序。

多个\expandafter

如何将\a\b\c这仨宏的展开顺序颠倒一下呢?
为了叙述方便,我们以 $\ex_i$ 代表第i个\expandafter
那么$\ex_1\ex_2\ex_3\a\ex_4\b\c$,就可以完成这个工作。
解析如下:
首先执行$\ex_1$,导致$\ex_2$被保存下来,然后Tex看到了$\ex_3$,发现这哥们还是一个\expandafter,那就继续往前看,就会将\a,保存下来(注意,目前为止,保存下来的有$\ex_2$,\a,而且执行过的$\ex_i$就没了。)
开始执行$\ex_4$,此时将\b保存下来,展开\c
ok,目前已经保存的tokens为,$\ex_2$,\a\b,将这个列表放到展开后的\c前面。
现在执行$\ex_2$,我们还得保存\a,展开\b
好了,最后保存列表里只有\a了,将其展开即可。

一个实际例子

tonjithesis.cls有这么一段用来设置cover的:

\def\tongji@define@term#1{
  \expandafter\gdef\csname #1\endcsname##1{
    \expandafter\gdef\csname tongji@#1\endcsname{##1}}
  \csname #1\endcsname{}}
\tongji@define@term{secretlevel}
\tongji@define@term{secretyear}
\tongji@define@term{ctitle}
\tongji@define@term{cdegree}

看懂了上面的例子之后,很容易得出来这个\tongji@define@term的庐山真面目,就拿\tongji@define@term{secretlevel}来说:
\gdef\secretlevel#1{\gdef\tongji@secretlevel{#1}}

(注,用一个宏定义另一个宏的##1技巧,我们在Tex for the impatient的笔记已经介绍过了,回忆一下就是:\def\first#1{\def\second##1{#1/##1}}
这样,当我们调用\first{One}的时候,就会将\second定义成:\def\second#1{One/#1}

好了,\gdef\secretlevel#1{\gdef\tongji@secretlevel{#1}}这么定义之后,我们就可以用\secretlevel{绝密}来定义一个\tongji@secretlevel宏了,接着可以用\tongji@secretlevel来表示密级,进而将其用于cover的排版。
而用户只需要调用\secretlevel{绝密}这么一个简单的命令就行了。

一种奇怪的用法

当我们需要奇怪的宏名的时候,可以配合\csname来实现这一个需求。
例如:
\expandafter\def\csname a?a-4\endcsname{...}
这样\a?a-4就是一个宏名了。
可想而知,如果没有\expandafter,上面也就是重新定义了\csname.