-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathchapitre10.tex
1607 lines (1288 loc) · 59.5 KB
/
chapitre10.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\chapter{装饰}
\begin{epigraphe}{《圣经·雅歌》7:10}
我说,我要上这棕树,抓住枝子。\\愿你的两乳好像葡萄累累下垂,\\你鼻子的气味香如苹果。\\你的口如上好的酒,女子说,\\为我的良人下咽舒畅,流入睡觉人的嘴中。
\end{epigraphe}
那本章的主要思路是介绍,介绍那些为生成文档中个别部分而被个性化修改的\LaTeX 的标准工具,间或可以从中看到些用于``调香''的宏。这些个性化设置可以应用于各个层级:使用包的选项,如设置页眉;偶尔涉足宏定义,如设置章节的展现风格;更深入地处理宏,如处理内容的表格。本章的一部分聚焦于我们可以从包\textsf{fancyvrb}中调用的工具。作为本章的末尾,我们会去抨击一下法文的引号。
\section{索引的外观} % 这节翻译得是什么破玩意
为了修改索引的外观,需要明白,当我们大手一挥噼里啪啦地写下如下指令的时候,我们实际上就生成了一个文件\codereplace{文档}\dm{.ind}:
\dmh{makeindex \codereplace{文档}}
该文件包含了类似下面列出的内容:
\begin{dmd}
\verb|\begin{theindex}| \quad$\leftarrow$\textsf{文前部分}\\
~\\
\verb|\item Cosmic debris, 12,34|\\
~\\
\verb|\indexspace| \quad$\leftarrow$\textsf{分组间的空间}\\
~\\
\verb|\item Debra kadabra, 23| \quad$\leftarrow$\textsf{入口,分割符,页码}\\
~\\
\verb|\end{theindex}| \quad$\leftarrow$\textsf{文后部分}
\end{dmd}
实际上,该代码会从带有预定义值且可被修改的一般性实体中生成。为了证明这个观点,只需要知道,程序\textsf{makeindex}可以生成一个包含\LaTeX 代码外内容的\dm{.ind}文件。为了理解一般性实体的职责,可以用如下方式描述\textsf{makeindex}的工作。
\begin{enumerate}
\item 根据实体\dm{preamble}的值来写入文前部分。
\item 对于每个\dm{.idm}文件:
\begin{enumerate}
\item 写入实体\dm{item\_0}的内容;
\item 写入入口(本例中为``Cosmic debris'');
\item 写入分割符(实体\dm{delin\_0}的值);
\item 写入页码。
\end{enumerate}
\item 在每个分组的结尾(即首字母切换时),写入实体\dm{group\_skip}的内容;
\item 根据\dm{postamble}的值写入文后部分。
\end{enumerate}
上述实体的默认值如下:
\begin{center}
\begin{dmd}
\begin{tabular}{|l|l|}
\hline
preamble & \verb+"\\begin{theindex}\n"+\\
item\_0 &\verb+"\n \\item"+\\
delim\_0 & ", "\\
group\_skip & \verb+"\n\n \\indexspace\n"+\\
postamble & \verb+"\n\n\\end{theindex}\n"+\\
\hline
\end{tabular}
\end{dmd}
\end{center}
这些值可以使用通常带有后缀名\dm{.ist}的风格文件作为媒介来修改。可以通过以下方式在调用\textsf{makeindex}时使用:
\dmh{makeindex -s \codereplace{风格}.ist \codereplace{文件}}
如此一来,为了生成文档的标题,我们可以一开始就重新定义一二级间的分隔符:
\begin{dmd}
\begin{verbatim}
delim_0 " \\dotfill \ "
delim_1 " \\dotfill \ "\end{verbatim}
\end{dmd}
我们将默认用于分隔索引入口和页码的逗号替换成了省略号。接下来,通过严谨地阅读\textsf{makeindex}的文档\jz{
可参见参考文献的实用引用后的提醒。
},可以注意到要求\textsf{makeindex}为入口组和代表分组的字母间生成空间的礼貌方式如下:
\begin{dmd}
headings\_flag 1
\end{dmd}
这里,代表分组的字母会表示为大写,并且借助实体\dm{heading\_prefix}和\dm{heading\_suffix}的内容框起。无所谓——为了生成我们美丽的带阴影的字盒,我们可以在风格文件中这样写:
\begin{dmd}
\begin{verbatim}
heading_prefix "{\\large\\sffamily\\bfseries\\shadowbox{"
heading_suffix "}\\hfill}\\nopagebreak\n"\end{verbatim}
\end{dmd}
这段你已经可以看懂的示例内容,就会生成我们需要的字盒。例如对于字母C:
\begin{codelist}[10.1]{
{\large\sffamily\bfseries%
\shadowbox{C}\hfil}\nopagebreak
}
\begin{verbatim}
{\large\sffamily\bfseries%
\shadowbox{C}\hfil}\nopagebreak\end{verbatim}
\end{codelist}
这段指令会被\dm{group\_skip}的内容覆盖掉。而我们稍早前说过,\dm{group\_skip}的默认值是\verb|\indexspace|。在研究了几个月之后\jz{
开玩笑的。我是想说,只花了几秒……好吧,几分钟。
},我们成功地在\dm{book.cls}中发现了该指令的定义,并且将分组间空间略微扩大了些:
\begin{dmd}
\renewcommand\indexspace{%
\par \vskip 20pt plus5pt minus3pt\relax}
\end{dmd}
\begin{ii}
本小节中,我们只是非常简单地看了看makeindex提供的功能。除了在《\LaTeX 伴侣》中能找到的信息,Debian环境下关于此工具的说明书中提供了我们可以定义的一半入口的详尽列表。由P.陈(P. Chen;音译)和M.A.哈林森(M. A. Harrinson)编写的文件\dm{ind.dvi}同样是初学索引自定义的良好开端。
\end{ii}
\section{标题的外观}
在本节,我们会介绍我们修改\LaTeX 标准(篇、章、节等)标题外观的方式。
\subsection{目录中的编号}
作为开始操作目录的前提条件,需要掌握两个计数器:
\begin{enumerate}
\item \dm{secnumdepth}(英:\emph{section numbering depth}),可以明确文档中标题编号的层级;
\item \dm{tocdepth}(英:\emph{table of contents depth}),可以定义目录标题的最大层级(或称最大深度)。
\end{enumerate}
为了使用这两个计数器,还需要了解\LaTeX 为各标题连接层级的方法。以下是各标题的层级:
\begin{center}
\begin{tabular}{|c|r||c|r|}
\hline
标题 & 层级 & 标题 & 层级\\
\hline
\dm{part} & -1 & & \\
\dm{chapter} & 0 & \dm{subsubsection} & 3\\
\dm{section} & 1 & \dm{paragraph} & 4\\
\dm{subsection} & 2 & \dm{subparagraph} & 5\\
\hline
\end{tabular}
\end{center}
如此一来,将\verb|secnumdepth|赋值为1、将\verb|tocdepth|赋值为2,则可以让标题编号至各\verb|\section|,同时将层级少于\verb|\subsection|的标题插入目录。
\subsection{节和更少的层级}
在\TeX 系统的文件\dm{book.cls}中,我们可以找到如下代码\jz{
稍微简化了一些……
}:
\begin{dmd}
\begin{verbatim}
\newcommand{\section}{%
\@startsection%
{section} % 标题名称
{1} % 标题层级
{0pt} % 缩进
{-3.5ex plus -1ex minus -.2ex}% 段前纵向空间
{2.3ex plus.2ex}% 段后纵向空间{\normalfont\Large\bfseries}} % 标题外观\end{verbatim}
\end{dmd}
该段代码定义了节标题的生成方式。可以观察到,指令\verb|\section|调用了指令\verb|\@startsection|,而后者需要6各参数:
\begin{itemize}
\item 标题名称,如\dm{section}、\dm{subsection}等;
\item 标题层级,1对应\dm{section},2对应\dm{subsection},3对应\dm{subsubsection},等等;
\item 缩进;
\item 标题前的纵向空白;
\item 标题后的纵向空白;
\item 用于确定标题本身格式的一系列\emph{声明}。
\end{itemize}
因此,我们可以注意到\LaTeX 默认为类型\dm{book}设定的版式如下。
\begin{itemize}
\item 无缩进(\dm{0pt})。
\item 标题前的纵向空间为\dm{3.5ex},带有正向\dm{-1ex}和负向\dm{-.2ex}的允差。
\item 标题后的纵向空间为\dm{2.3ex},带有正向\dm{.2ex}的允差。可以注意到,如果空间为负,则段落开头会紧接标题,而不会重起一段。
\item 标题加粗加大,使用``常规''(normal)字体。
\end{itemize}
为了定义本文档使用的标题样式,我们引入三个长度,分别用于\dm{section}、\dm{subsection}、\dm{subsubsection}的缩进:
\begin{dmd}
\begin{verbatim}
\newlength{\sectiontitleindent}
\newlength{\subsectiontitleindent}
\newlength{\subsubsectiontitleindent}\end{verbatim}
\end{dmd}
长度值如下:
\begin{dmd}
\begin{verbatim}
\setlength{\sectiontitleindent}{-1cm}
\setlength{\subsectiontitleindent}{-.5cm}
\setlength{\subsubsectiontitleindent}{-.25cm}\end{verbatim}
\end{dmd}
此外,我们为标题还定义了特殊的字体,具体如下:
\begin{dmd}
\begin{verbatim}
\newcommand{\sectionfont}{%
\fontencoding{\encodingdefault}%
\fontfamily{pag}% \fontseries{bc}%
\fontshape{n}% \selectfont}\end{verbatim}
\end{dmd}
该指令可以选用PostScript字体AvantGarde的加粗紧缩版本(参阅9.4节)%TODO 解释中文的使用
。最终,我们使用了以下指令来定义节标题外观:
\begin{dmd}
\begin{verbatim}
\renewcommand{\section}{%
\@startsection%
{section}%
{1}%
{\sectiontitleindent}%
{-3.5ex plus -1ex minus -.2ex}%
{2.3ex plus.2ex}% {\sectionfont\Large}}\end{verbatim}
\end{dmd}
对于更少层级的标题,我们也编写了等价的指令。
\subsection{章}
通过深入研究文件\dm{book.cls},我们可以找到有关\LaTeX 生成章首内容的信息。
\subsubsection{原则}
在文件\dm{book.cls}中,我们可以找到以下指令:
\begin{dmd}
\begin{verbatim}
\newcommand{\chapter}{%
...
\thispagestyle{plain}%
...
\secdef\@chapter\@schapter} % 我们感兴趣的行\end{verbatim}
\end{dmd}
指令\verb|\chapter|本身会调用两个不同的指令:
\begin{enumerate}
\item \verb|\@chapter|,用于被编号的章标题;
\item \verb|\@schapter|,用于不被编号的章标题(\dm{s}代表\emph{star},即``星号'',对应指令\verb|\chapter*|)。
\end{enumerate}
在英勇地(同样在文件\dm{book.cls}中)查找这两条指令的定义之后,我们找到了下面这类东西:
\begin{dmd}
\begin{verbatim}
\def\@chapter[#1]#2{% ...
\refstepcounter{chapter}%
% 终端上的消息:
\typeout{\@chapapp\space\thechapter.}
\addcontentsline{toc}{chapter}% 在目录中添加标题
...
\if@twocolumn
...
\else% 针对不分栏的文档
\@makechapterhead{#2}% 我们感兴趣的代码行
\fi}\end{verbatim}
\end{dmd}
这段代码把我们领上道了……实际上,\verb+\@makechapterhead+(可以按字面翻译为``制作章首装饰'')正是我们更改图案所需要重定义的指令。经过进一步的搜索,我们可以发现指令\verb|\@makeschapterhead|能够生成未编号的章首装饰。这两条指令接受章名作为其参数。
\subsubsection{必要的小工具}
我们定义了环境\dm{cadrechap},用于简单地讲右边距加宽2厘米:
\begin{dmd}
\begin{verbatim}
\newenvironment{cadrechap}%
{\begin{list}{}{%
\setlength{\leftmargin}{0pt}%
\setlength{\rightmargin}{-2cm}% 宽敞些
\setlength{\itemindent}{0pt}%
\setlength{\labelsep}{0pt}%
}\item}%
{\end{list}}\end{verbatim}
\end{dmd}
同时,可以使用布尔值\dm{@mainmatter}来获取我们目前是否处于文档的``中心''——这是针对指令\verb|\mainmatter|被调用的情况。
\subsubsection{严格的章首装饰}
本文档中,生成章首装饰的指令可以看作两个微型页面的组合。%TODO minipage
\begin{enumerate}
\item 在左侧的是微型页面字盒。我们指定了它的高度,以便放置微型摘要(参见\S 10.7)。
\item 在右侧的是包含``章''一词和章号的字盒。
\end{enumerate}
\newcommand{\boite}[1]{%
{\setlength{\fboxrule}{.2pt}%
\setlength{\fboxsep}{-\fboxrule}%
\fbox{#1}}}
\DeclareFixedFont{\fnumfont}{T1}{phv}{b}{n}{32pt}
\DeclareFixedFont{\fnomfont}{T1}{phv}{b}{n}{12pt}
\DeclareFixedFont{\ftitrefont}{T1}{phv}{b}{n}{16pt}
\newcommand{\fairechapitre}[1]{%
\noindent\begin{minipage}{\linewidth}%
\boite{\begin{minipage}[t][3cm][c]{.75\textwidth}%
\centering%
为\\微型摘要\\准备的\\微型页面
\end{minipage}}%
\boite{\begin{minipage}[t]{.25\textwidth}
\begin{flushright}
{\fnomfont\chaptername}\\[.5cm]
{\fnumfont\thechapter}
\end{flushright}
\end{minipage}}
\end{minipage}\par
\begin{flushright}\ftitrefont#1\end{flushright}}
\fairechapitre{Zhang biaoti}%TODO font
实现此类字盒组合的框架如下:
\begin{dmd}
\begin{verbatim}
\begin{cadrechap}
\begin{minipage}[t][6cm][t]{0.75\linewidth}
% 这里插入微型摘要
\end{minipage}
\begin{minipage}[t]{0.25\linewidth}
% 这里插入章号
\end{minipage}
\begin{flushright}
% 这里插入章标题
\end{flushright}
\end{cadrechap}\end{verbatim}
\end{dmd}
此处无疑需要注意到,左侧的字盒(即接收微型目录的字盒)带有可指定的高度,用于以一致的方法来生成章首装饰而无须关注章中的节数(即无须关注微型目录的高度)。接下来,为不同元素定义不同的字体,就可以完成章首装饰的定义。在本文档中,我们的定义如下:
\begin{dmd}
\begin{verbatim}
% 章号
\DeclareFixedFont{\chapnumfont}{T1}{phv}{b}{n}{80pt}
% ``章''一词
\DeclareFixedFont{\chapchapfont}{T1}{phv}{b}{n}{16pt}
% 章标题
\DeclareFixedFont{\chaptitfont}{T1}{phv}{b}{n}{24.88pt}\end{verbatim}
\end{dmd}
\DeclareFixedFont{\chapnumfont}{T1}{phv}{b}{n}{80pt}
\DeclareFixedFont{\chaptitfont}{T1}{phv}{b}{n}{24.88pt}
因此,有如下指令:
\begin{codelist}[10.2]{
{\chapnumfont 8}
{\chaptitfont Oula !}
}
\begin{verbatim}
{\chapnumfont 8}
{\chaptitfont Oula !}\end{verbatim}
\end{codelist}
\subsection{部分}
在文件\dm{book.cls}中,我们可以找到指令\verb|\part|的定义:
\begin{dmd}
\begin{verbatim}
\newcommand\part{%
\cleardoublepage
\thispagestyle{plain}
[...]
\null\vfil
\secdef\@part\@spart}\end{verbatim}
\end{dmd}
该定义告诉我们,正如各章一样,指令\verb|\part|会调用两条独立的指令,用于生成编号和不编号的部分(分别借助指令\verb|\@part|和\verb|\@spart|)。在之前的实践中,我们指定了页面的风格,使得各部分的开头为空(即没有页码和部分开头的装饰等),指令如下:
\begin{dmd}
\begin{verbatim}
\newcommand\part{%
\cleardoublepage
\thispagestyle{empty}% 代替默认的plain
[...]
\null\vfil% 空字盒和竖直方向的弹性空间
\secdef\@part\@spart}\end{verbatim}
\end{dmd}
接下来,我们可以查看指令\verb|\@part|的定义。该指令用于生成展示文档部分的页:
\begin{dmd}
\begin{verbatim}
\def\@part[#1]#2{%
[...]
{\centering % 居中
[...]
\huge\bfseries \partname\nobreakspace\thepart
\par
\vskip 20\pt
[...]
\Huge \bfseries #2\par}%
\@endpart}\end{verbatim}
\end{dmd}
通过查看这段代码,我们了解到,展现部分的页面由一行加粗加大的``部分''字样和部分的序号构成\jz{
实际上,在联动了包\textsf{babel}和选项\dm{french}后,这两个指令会被重定义,以生成形如``Première partie''(第一部分)的内容。
}:
\begin{dmd}
\verb|\huge\bfseries \partname\nobreakspace\thepart|
\end{dmd}
在距离20点的下方,是部分的标题(存储在参数\verb|#2|中)。对于此文档,我们以如下方式重定义了指令\verb|\@part|:
\begin{dmd}
\begin{verbatim}
\def\@part[#1]#2{%
[...]
{\centering
\interlinepenalty \@M
\normalfont
[...]
\partnumfont \thepart % 只显示部分的序号
\par
\vskip 50\p@% 将20点改为50点
\partfont #2\par}% 使用自定义字体的标题
\@endpart}\end{verbatim}
\end{dmd}
为了与章首装饰保持一致,我们定义指定字体的指令如下:
\begin{dmd}
\begin{verbatim}
\newcommand{\partfont}{%
\fontencoding{\encodingdefault}\fontfamily{phv}%
\fontseries{bc}\fontshape{n}% \fontsize{32}{34}%
\selectfont}
\DeclareFixedFont{\partnumfont}{T1}{phv}{bc}{n}{80}%\end{verbatim}
\end{dmd}
\begin{exclamation}
我们也应注意到,指令\verb+\@part+依靠调用另一条指令作为结尾:\verb|\@endpart|。通过查看文件\dm{book.cls}可以看到,这样的结尾可以阻止来自指令\verb|\part|的纵向弹性空间,并跳过一个空白页……
\end{exclamation}
\section{几何}
本文档中,各页面中的不同尺寸借助包\textsf{geometry}使用如下指令定义:
\begin{dmd}
\begin{verbatim}
\geometry{%
a4paper,
body={150mm,250mm},
left=25mm,top=25mm,
headheight=7mm,headsep=4mm, marginparsep=4mm,
marginparwidth=27mm}\end{verbatim}
\end{dmd}
这会分别定义如下元素(如图\ref{fig:10.1}所示):
\begin{itemize}
\item 版心宽150 mm,高250 mm;
\item 版心在页面上的位置为左边距25 mm、上边距25 mm;
\item 页眉高7 mm,页眉与正文的间距为4 mm;
\item 页面尺寸为标准A4;
\item 用于页边注释的页边距为2.7 cm。
\end{itemize}
\begin{figure}[ht]
\centering
\includegraphics{img/geometry}
\caption{定义文档几何样式的部分尺寸}
\label{fig:10.1}
\end{figure}
以通常的方式来讲,正如图\ref{fig:10.1}展现的,包\textsf{geometry}可以定义一定数量的尺寸。我们可以以选项的方式将这些尺寸传递给\verb|\usepackage|,也可以借助指令\verb|\geometry|。
\begin{description}
\item[页面尺寸]%TODO 此处如何换行,下同
\begin{itemize}
\item 若使用预定义中的格式,可以使用\dm{a4paper}、\dm{a5paper}等。
\item 若要自由地指定纸张尺寸,例如针对会使用碎纸机销毁的文档的尺寸,可以使用\dm{paperwidth=}\codereplace{尺寸}和\dm{paperheight=}\codereplace{尺寸}。
\end{itemize}
\item[文本]
\begin{itemize}
\item 可以使用\dm{body=\{\codereplace{宽度},\codereplace{高度}\}};
\item 也可以使用\dm{width=}\codereplace{宽度}和\dm{height=}\codereplace{高度};
\item 文本在页面内的位置由参考点确定,可以使用\dm{top=}\codereplace{纵向位置}和\dm{left=}\codereplace{水平位置}确定参考点位置。
\end{itemize}
\item[页面顶端和底部]
\begin{itemize}
\item 页面中为页面预留的高度可以借助神奇的表达式\dm{headheight=}\codereplace{高度}定义,页眉相对于版心的位置可以借助指令\dm{headsep=}\codereplace{空间}指定;
\item 页脚的位置可以通过长度\dm{footskipp=}\codereplace{空间}指定,该长度可以定义版心底部和页脚第一行间的空间。
\end{itemize}
\item[页边注释] 秉承着同样的精神,页面中为边注预留的空间的宽度和位置可以借助两个长度定义:\dm{marginparwidth=}\codereplace{宽度}和\dm{marginparsep=}\codereplace{空间}
\end{description}
\begin{exclamation}
包geometry中,涉及页眉、页脚、边注的尺寸默认算作版心\emph{外}的部分。有一些指令可以将这些尺寸中的一个或多个包含到版心内部来完成计算。例如,我们可以说``我希望版心宽度为10厘米,包含边注''。关于更多相关细节,请参阅包文档。
\end{exclamation}
\section{页眉和页脚}
版心上下的空间分别成为页眉和页脚,可以借助包\textsf{fancyhdr}来定制。定制的基本原则很简单\jz{
在读完接下来的内容后,你无疑会开始质疑这里说的``简单''一词……
},只需要使用以下指令来指明我们想要使用借助包\textsf{fancyhdr}定义的页眉和页脚。该包默认会在页面下方和页脚上方生成一条水平线段,线段粗细分别由\verb|\footrulewidth|和\verb|\headrulewidth|定义。接下来,我们使用以下指令:
\begin{itemize}
\item \verb|\fancyhead|,来定义页眉;
\item \verb|\fancyfoot|,来定义页脚。
\end{itemize}
这两条指令都可以接收由一个或两个以下字符组成的序列构成的参数:
\begin{itemize}
\item \dm{E}或\dm{O},用于指明页码的奇偶性(偶数即\emph{even},奇数即\emph{odd});
\item \dm{R}、\dm{L}或\dm{C},用于指明我们想在哪个位置生成信息,分别指代右侧、左侧或居中。
\end{itemize}
示例如下:
\begin{dmd}
\begin{verbatim}
\fancyhf{} % 清除页面并开始
% 【页眉】
% 作者姓名首字母偶数页靠右,奇数页靠左:
\fancyhead[RE,LO]{VL}
% 页码居中:
\fancyhead[C]{\thepage}
% 节号奇数页靠右,
% 偶数页靠左:
\fancyhead[LE,RO]{\thesection}
% 【页脚】
% 图片奇数页靠右,偶数页靠左:
\fancyfoot[RO,LE]{\includegraphics[height=4ex]{punch}}
% 标题奇数页靠右,偶数页靠左:
\fancyfoot[LO,RE]{%
关于\LaTeX{}的那些你想知道的问题}
% 线条粗细
\renewcommand{\footrulewidth}{3pt}\end{verbatim}
\end{dmd}
\fancyhf{}
\fancyhead[RE,LO]{VL}
\fancyhead[C]{\thepage}
\fancyhead[LE,RO]{\thesection}
\fancyfoot[RO,LE]{\includegraphics[height=4ex]{punch}}
\fancyfoot[LO,RE]{关于\LaTeX{}的那些你想知道的问题}
\renewcommand{\footrulewidth}{3pt}
\subsection{章首页的情况}
在类型\dm{book}中,\LaTeX 会自动为每章的第一页调用风格\dm{plain}。为了使包\textsf{fancyhdr}为这些页面定义新风格,可以使用如下指令:
\begin{dmd}
\begin{verbatim}
% 章首页的情况
\fancypagestyle{plain}{%
\fancyhf{}% 全部清空
\fancyfoot[C]{\thepage}% 页面底部的页码
% 清空所有线条
\renewcommand{\headrulewidth}{0pt}%
\renewcommand{\footrulewidth}{0pt}}\end{verbatim}
\end{dmd}
可以注意到,本书各章的章首正是采用了这种风格……
\subsection{章首前的空白页}
在类型\dm{book}的双面模式下(正是本文档对应的情况),\LaTeX 会默认在奇数页——这在排版术语中称作``单面''(belle page)——开始新的一章。为了实现这一点,\LaTeX 在不同的内部指令中调用了指令\verb+\cleardoublepage+。这样可以在必要时在章的首页前插入一个空白页。默认情况下,该空白页会带有目前使用的页眉和页脚。在本文档中,我们针对这些页面修改了文件\dm{latex.ltx}中的指令\verb|\cleardoublepage|,指定了一种``空白''的风格:%TODO 还没搞
\begin{dmd}
\begin{verbatim}
\renewcommand{\cleardoublepage}{% 重定义该指令
\clearpage\ifodd\c@page\else
\hbox{}
\vspace*{\fill}
\thispagestyle{empty}% 添加此行
\newpage
\fi}\end{verbatim}
\end{dmd}
你可以翻阅本书,看看章首前的页面是否是空白的……
\subsection{标记的机制}
你无疑已经注意到了,本书的页眉带有一些与文本相关的内容。实际上,针对偶数页(出现在左侧的页面),我们插入了章标题;针对奇数页(出现在右侧的页面),我们插入了该页出现的最后一节的节标题。\LaTeX 部署了一种\emph{标记}机制,使得我们可以实现这一点。这里将尝试解释这种机制。
\begin{exclamation}
这里不妨解释一下:\LaTeX 和\TeX 生成一个页面是,它们会根据从所涉页面收集来的信息来制备页眉和页脚。因此,生成页眉和页脚是编译页面的后置步骤。
\end{exclamation}
\subsubsection{指令\dm{\backslash markboth}和\dm{\backslash markright}}
设有以下指令:
\begin{dmd}
\backslash markboth\{\codereplace{文本$_{\mbox{左}}$}\}\{\codereplace{文本$_{\mbox{右}}$}\}
\end{dmd}
或:
\begin{dmd}
\backslash markright\{\codereplace{文本}\}
\end{dmd}
想象参数\codereplace{文本$_{x}$}存储在栈和队列中。根据这种想法,有:
\begin{itemize}
\item \verb|\markboth|将\codereplace{文本$_{\mbox{左}}$}入栈,将\codereplace{文本$_{\mbox{右}}$}存入队列;
\item \verb|\markright|将\codereplace{文本}存入队列。
\end{itemize}
在一个页面中,这两个``标记''指令可以调用多次,也可以一次都不调用。在\TeX 结束版心的排版,在生成页眉和页脚时,会探索栈和队列的参数。这借助了以下指令:
\begin{itemize}
\item \verb|\leftmark|返回栈顶,即\emph{上一次调用}\verb|\markboth|时的\codereplace{文本$_{\mbox{左}}$};
\item \verb|\rightmark|返回队列头,即\emph{第一次调用}\verb|\markboth|时的\codereplace{文本$_{\mbox{右}}$},或\emph{第一次调用}\verb|\markbot|时的\codereplace{文本}。
\end{itemize}
\begin{exclamation}
我们这里介绍的``队列''有一个小巧思:只要页面中没有``标记''指令添加数据,那么队列就会保持此前的页面中\emph{最后插入的信息}。指令\verb|\markboth|和\verb|\markright|一出现,``队列''就被清空。
\end{exclamation}
另一个理解这种标记机制的方法可以描述如下:
\begin{itemize}
\item \verb|\leftmark|包含入栈的最后一条信息(借助\verb|\markboth|的第一个参数);
\item 如果我们在页面上放置了一词\verb|\rightmark|,则它包含``队列''的第一条信息,否则它包含队列中的最后一条信息(借助\verb|\markboth|的第二个参数或\verb|\markright|的参数)。
\end{itemize}
\begin{ii}
供你参考的是,作者使用了这些指令来生成了带有几十个名称和照片的相册。这里的思路是去探索通过页眉显示页面上第一个和最后一个名称的机制——这种页眉跟字典很像。为了实现这个目的,只需要为每个人(包含名称和照片)调用以下指令:
\begin{dmd}
\backslash markboth\{\codereplace{老铁的名称}\}\{\codereplace{老铁的名称}\}
\end{dmd}
接下来,在左侧页面页眉中插入指令\verb|\rightmark|,在右侧插入\verb|\leftmark|……
\end{ii}
\subsubsection{与段落指令的互动}
在各章、节、小节等结构的开头,\LaTeX 的一条内部指令会调用前文介绍过的标记指令,以将疑似可以丰富页眉和页脚内容的信息存储起来。这些指令的名称如下:
\begin{itemize}
\item \verb|\chaptermark|,适用于章;
\item \verb|\sectionmark|,适用于节;
\item ……
\end{itemize}
这些指令会等待包含章或段落标题的参数。对于本书,前面列出的两条指令采用如下方式定义:
\begin{dmd}
\begin{verbatim}
% #1包含节标题
\renewcommand{\sectionmark}[1]{%
\markright{\sectionfont\thesection\ #1}}
% #2 包含章标题
\renewcommand{\chaptermark}[1]{%
\markboth{\sectionfont#1}{}}\end{verbatim}
\end{dmd}
接下来有:
\begin{dmd}
\begin{verbatim}
\fancyhead[LE,RO]{\thepage}
\fancyhead[LO]{\rightmark}
\fancyhead[RE]{\leftmark}\end{verbatim}
\end{dmd}
这样一来:
\begin{itemize}
\item 在偶数页的右侧,我们可以找到上一个章标题(\verb|\leftmark|);
\item 在奇数页的左侧,我们可以找到当前页的第一个\verb|\section|,包含序号和标题,或是上一个\verb|\section|的序号和标题(\verb|\rightmark|)……
\end{itemize}
%TODO 对于前置页面的单章双节?
\fancyhf{}
% \fancyhead[LE]{\bfseries\thepage}
% \fancyhead[RO]{\bfseries\thepage}
\fancyhead[LE]{\ongletpaire\bfseries\thepage}
\fancyhead[RO]{\bfseries\thepage\ongletimpaire}
\fancyhead[LO]{\texttt{\backslash rightmark}的值为``\rightmark{}'',\texttt{\backslash leftmark}的值为``\leftmark''}
\fancyhead[RE]{\texttt{\backslash rightmark}的值为``\rightmark{}'',\texttt{\backslash leftmark}的值为``\leftmark''}
\renewcommand{\footrulewidth}{0pt}
如果你不相信,可以亲自看看本章的页眉。
\subsection{文档的组织}
需要知道,对于形如本书的文档,\LaTeX 可以识别出三大部分,在英文中分别称作\emph{front matter}、\emph{main matter}和\emph{back matter},分别代表文章的开头(通常带有前言和摘要)、作为主体的部分、用于收尾的部分(通常带有目录、附录、参考文献、术语字典等)。因此,我们应该明确,\LaTeX 文档的书写形式如下:
\begin{dmd}
\backslash documentclass\{\codereplace{文档类型}\}
\begin{verbatim}
\begin{document}
\frontmatter % 前言
[...]
\mainmatter % 主体部分
[...]
\backmatter % 用于收尾
[...]
\end{document}\end{verbatim}
\end{dmd}
接下来,我们将会着手逐一修改这三个指令。目前你需要知道的是,类型\dm{book}种定义了一个布尔值:
\begin{dmd}
\verb|\newif\if@mainmatter|
\end{dmd}
\LaTeX 默认使用该值来获取当前我们是否处于``main matter''中。此外,我们的文档中还有另一个布尔值:
\begin{dmd}
\verb+\newif\if@frontmatter+
\end{dmd}
该值可以使我们为文档中介绍性的部分进行特殊处理。界定三大部分的三个指令定义如下:
\begin{dmd}
\begin{verbatim}
\renewcommand\frontmatter{%
\cleardoublepage
\@frontmattertrue
\@mainmatterfalse
\pagenumbering{roman}% 以罗马数字编号
}
\renewcommand\mainmatter{%
\cleardoublepage
\@mainmattertrue
\@frontmatterfalse
\pagenumbering{arabic}% 以阿拉伯数字编号
}
\renewcommand\backmatter{%
\cleardoublepage
\@frontmatterfalse
\@mainmatterfalse
}\end{verbatim}
\end{dmd}
在\LaTeX 源代码中一番翻找后,我们就可以明白,指令\verb|\pagenumbering|能够修改编号方式,并且将页码计数器重置为1。
%
% TODO on remet tous commme c'�tait avant
%
\fancyhf{}
% \fancyhead[LE]{\bfseries\thepage}
% \fancyhead[RO]{\bfseries\thepage}
\fancyhead[LE]{\ongletpaire\bfseries\thepage}
\fancyhead[RO]{\bfseries\thepage\ongletimpaire}
\fancyhead[LO]{\bfseries\rightmark}
\fancyhead[RE]{\bfseries\leftmark}
\renewcommand{\footrulewidth}{0pt}
\subsection{以``小型大写''罗马数字为前言编号}
鄙人坚持认为,前言部分的页码应当以小型大写罗马数字标示。很不幸,我们不能写成这样:
\begin{dmd}
\verb|\renewcommand{\thepage}{\textsc{\roman{page}}}|
\end{dmd}
这是因为,这样的写法会导致索引的不兼容。这里的思路是按如下步骤处理:
\begin{enumerate}
\item 使用小写罗马数字编号;
\item 在页脚显示\verb|\textsc{\thepage}|;
\item 修改指令\verb|\index|来使页码显示为小型大写。
\end{enumerate}
这样一来,我们需要在\verb|\frontmatter|的定义中添加如下内容:
\begin{dmd}
\begin{verbatim}
\let\indexORI\index% 保存初始的定义
\renewcommand{\index}[1]{\indexORI{##1|textsc}}
\fancyfoot{}
\fancyhead[LE,RO]{\textsc{\thepage}}\end{verbatim}
\end{dmd}
在\verb|\mainmatter|的定义中添加如下内容:
\begin{dmd}
\begin{verbatim}
\let\index\indexORI% 以回到初始的定义\end{verbatim}
\end{dmd}
为了完美地达到我们的严格标准,我们也会修改章首页的风格:
\begin{dmd}
\begin{verbatim}
\fancypagestyle{plain}{%
\fancyhf{}
\if@frontmatter% 前言
\fancyfoot[C]{\textsc{\thepage}}
\else
\fancyfoot[C]{\thepage}
\fi
\renewcommand{\headrulewidth}{0pt}
\renewcommand{\footrulewidth}{0pt}}
\makeatother\end{verbatim}
\end{dmd}
\subsection{索引、参考文献和目录}
在类型\dm{book}中,定义了两种环境:
\begin{itemize}
\item \dm{thebibliography},用于生成参考文献;
\item \dm{theindex},用于生成索引。
\end{itemize}
此外,还定义了一个指令:
\begin{itemize}
\item \verb|\tableofcontents|,用于生成目录。
\end{itemize}
这些环境或指令被设计为可以生成带有页码和大写标题的页眉,即\verb|\bibname|、\verb|\indexname|和\verb|\contentsname|。例如,以下是\verb|\tableofcontents|的节选:
\begin{dmd}
\begin{verbatim}
\newcommand\tableofcontents{%
[...]
\chapter*{\contentsname
\@mkboth{%
\MakeUppercase\contentsname}%
{\MakeUppercase\contentsname}}%
\@starttoc{toc}%
[...]
}\end{verbatim}
\end{dmd}
我希望本文档的页眉不采用大写形式。有采用两种解决方式。
\begin{itemize}
\item 使用包\textsf{fancyhdr}的指令\verb|\nouppercase|,并在\verb|\backmatter|的定义中编写如下内容:
\begin{dmd}
\begin{verbatim}
% 大写页眉:
\fancyhead[LO]{\nouppercase\rightmark}
\fancyhead[RE]{\nouppercase\leftmark}%
\end{verbatim}
\end{dmd}
\item 重新复制并修改源于\dm{book.cls}的宏\verb|\tableofcontents|,将其中多次出现的指令\verb|\MakeUppercase|全部删除。对于索引和参考文献进行相同的操作。
\end{itemize}
本文档采用了第二种方式。我们同样在目录中插入索引和参考文献时,也同样可以感受到这种方式带来的优势——默认情况下,\LaTeX 和类型\dm{book}对此不兼容。因此,我们有了如下形式的环境\dm{theindex}:
\begin{dmd}
\begin{verbatim}
\renewenvironment{theindex} {%
[...]
% 插入至目录
\addcontentsline{toc}{chapter}{\indexname}
% 删除\MakeUppercase
\@mkboth{\indexname}{\indexname}
\thispagestyle{plain}
[...]
{\if@restonecol\onecolumn\else\clearpage\fi}\end{verbatim}
\end{dmd}
\section{``照抄''环境}
包\textsf{fancyvrb}和\textsf{listings}都包含可以生成带特殊符号文本的特性。其中,前者更加灵活,可以生成\dm{verbatim}种类的环境,特别是可以定制必要的边框和边距。最重要的是,它允许你从环境的正中央``逃回\LaTeX '',或者按英语国家的人所说的:\emph{to escape to \LaTeX }。换句话说,尽管是在符号\verb|\|、\dm{\{}、\dm{\}}都不起作用的环境中,我们仍然可以调用\LaTeX 的指令。
后者(\textsf{listings})致力于生成代码片段。它提供的大量功能中,同样包含可以逃回\LaTeX 的方法。这里我们推荐你借助本章使用的``真实复刻''示例探索一下这两个环境。
\subsection{跑个题,说说符号……}
在这里我想先说说\TeX 如何``消化吸收''我们喂给它的字符——我相信这题没有白偏\jz{
在做事低调这件事上,法国人似乎是专家,但我们不要偏太远了……
}。需要明白,符号可以被划分为16中类别,每个符号只能同时属于其中的一种。每种类别都可以由\TeX 特殊处理。例如,遇到符号\dm{\backslash}时,\TeX 会读取其后面的字符组,来识别指令(或\emph{控制序列})的名称;遇到符号\dm{\{}时,\TeX 会开启新的组;读取到符号\dm{\%}时,\TeX 会一路忽略接下来符号,直到当前行结束,也就是遇到标记``行末''的符号,等等。\TeX 可以识别的类别举例如下:
\begin{description}
\item[类0]控制符号(\LaTeX 中的\dm{\backslash});
\item[类1]组起始符号(\LaTeX 中的\dm{\{});
\item[类2]组结束符号(\LaTeX 中的\dm{\}});
\item[类11]字母;
\item[类14]注释(\LaTeX 中的\dm{\%})。
\end{description}
我们可以来找找乐子——虽然这样做挺``危险''——来修改各类别的内容。在下面的示例中,我们将\verb|\|、\dm{\{}、\dm{\}}转为字母,并且决定分别让\dm{/}、\dm{(}、\dm{)}出现在控制符号、组起始、组结束类别中。字符\verb+#+同样被修改了类别,现在它属于注释:
\begin{codelist}[10.3]{
\backslash bidule\{一些东西\} \textbf{加粗}\par
现在回到\LaTeX{}模式……
}
\begin{verbatim}
{ \catcode`\/=0 \catcode`\(=1
\catcode`\)=2 \catcode`\#=14
\catcode`\{=11 \catcode`\}=11
\catcode`\\=11
# 这行应该看不到……
\bidule{一些东西} /textbf(加粗)
)\par
现在回到\LaTeX{}模式……\end{verbatim}
\end{codelist}
此外,有趣的是,\TeX 可以让某些符号活跃起来(将其归入类13)。这样,这些符号就可以被定义为指令。以下是一个有些蠢的示例:
\begin{codelist}[10.4]{
3 加 4 = 7
}
\begin{verbatim}
\catcode`\+=13
\newcommand{+}{加}
3 + 4 = 7\end{verbatim}
\end{codelist}
这个示例中,我们让字符\dm{+}``活跃''了起来,并像定义指令那样定义了它。可以注意到,这里,我们曾可以不调用符号\dm{\backslash}就创建一个可用的指令。
\begin{ii}
需要知道,我们使用了包babel和法文扩展。一些双标点同样被设置为活跃,目的是防止在它们前面出现断字。此外,符号\dm{~}在\LaTeX 被视为活跃,你可以在交互式\LaTeX 绘画中看到其定义:
\begin{dmd}
\begin{verbatim}
*\show~
> ~=macro:
->\nobreakspace {}.
<*> \show~\end{verbatim}
\end{dmd}
\end{ii}
\subsection{基于包\textsf{fancyvrb}的上层建筑环境}
\dm{verbatim}之类的环境的目的是将字符的归属分别转化到对应的类中。此外,借助包\textsf{fancyvrb},可以定义哪些字符可以传递控制指令给\LaTeX 。在本文档中,环境\dm{unixcom}的定义如下:
\begin{dmd}
\begin{verbatim}
\DefineVerbatimEnvironment{unixcom}{Verbatim}{%
commandchars=¢« »,
frame=single, framerule=.4pt, framesep=1.5mm, gobble=2,
xleftmargin=15pt}\end{verbatim}
\end{dmd}
这个环境属于一种\dm{verbatim},但我们可以在其中``执行''\LaTeX 指令。这需要借助属于类0的符号\dm{¢}、属于类1的符号\dm{«},以及属于类2的符号\dm{»}——很显然,我们可以随意选择字符来实现这一点。然而,这样做需要秉持着符号应当易读且其用途几乎仅为向\LaTeX 传递控制指令的精神。
\begin{codelist}[10.5]{%这个序号原书没有显示出来,但确实占了一个号
为了显示变量的内容:
\dmh{echo \$\{}\codereplace{我的变量}\dm{\}}
}
\begin{verbatim}
为了显示变量的内容:
\begin{unixcom}
echo ${¢marg«我的变量»}
\end{unixcom}\end{verbatim}
\end{codelist}
%TODO 左边距根据原文修改
指令\celan{\S 11.1.1}\verb|\marg|可以将其变量放入尖括号并以倾斜形式显示。指令\verb|\DefineVerbatimEnvironment|的其他变量可以详细说明边框风格(参数\dm{frame}等)、左边距(参数\dm{xleftmargin}),以及指定每行第一组字符被系统地忽略(\dm{gobble})。正如包\textsf{fancyvrb}的文档中提到的,有很多其他选项可供使用。
我们创建的另一个此类环境用于在Auc\TeX 认可的附录中插入\textsf{Emacs}指令。此处涉及的环境(赐名为\dm{emacscom})的创建方式如下:
\begin{dmd}
\begin{verbatim}
\DefineVerbatimEnvironment{emacscom}{Verbatim}{%
commandchars=¢« »,
frame=leftline, framerule=1mm, framesep=2mm,
gobble=2, xleftmargin=15pt}\end{verbatim}
\end{dmd}
使用如下:
\begin{codelist}[10.6]{
在\textsf{Emacs}中玩俄罗斯方块:
\dmhmake{M-x tetris}
}
\begin{verbatim}
在\soft{Emacs}中玩俄罗斯方块:
\begin{emacscom}
M-x tetris
\end{emacscom}\end{verbatim}
\end{codelist}
\subsection{用于编程语言的环境}
包\textsf{listing}可以识别大量编程语言的语法。该包的一种简单的使用方式是借助一种很像\verb|\newenvironment|的指令创建它自带的环境:
\begin{dmd}
\begin{verbatim}
\lstnewenvironment{C}{\lstset{language=C}}{}\end{verbatim}
\end{dmd}
接下来,可以简单地编写代码:
\lstnewenvironment{C}{\lstset{language=C}}{}