-
Notifications
You must be signed in to change notification settings - Fork 5
/
cus-cn.tex
7477 lines (6218 loc) · 307 KB
/
cus-cn.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
\DocumentMetadata{}
\documentclass{cusdoc}
\hypersetup{pdfauthor={Longaster, \CusTeX},
pdftitle=\CusTeX 宏集手册,
pdfcreator={\XeLaTeX} with hyperref and \CusLaTeX}
\newsavebox\WaterMarkBox
\sbox{\WaterMarkBox}{\rotatebox{45}{\color{gray!30}\fontsize{100}{0}\sffamily \CusTeX}}
\background+[./watermark]{\copy\WaterMarkBox}
\newindextype[auto=true,filename=\jobname.idx,heading*={\section}]{\empty}
\setupindex[\empty,docchange]{auto=false}
\makeatletter
\setpagestyle*{fancy}[totalempty]{
\sethead [ol,er] {\CusTeX 宏集手册}
\sethead [or,el] {\headlink@warp\marked@title}
% \setfoot [or,el] {\texttt{longaster@163.com}}
\setfoot [ol,er] {第\thepage 页}
\setheadrulewidth {1pt}
}
\protected\def\normalsize{%
\@setfontsize \normalsize {10.53937}{12.64725}%
\abovedisplayskip 1\p@ \@plus 4\p@ \@minus 2\p@
\abovedisplayshortskip \z@ \@plus 2\p@
\belowdisplayskip \abovedisplayskip
\belowdisplayshortskip \abovedisplayshortskip
\let \@listi \@listI
}
\makeatother
\def\nofuncskip{\par\vskip-\bigskipamount\vskip\parskip\par}
\def\zhslash{/}
\newcommand\UNEXPANDEDRESULT{最终结果使用 \tn{unexpanded} (\cs{exp_not:n})包裹起来。}
\raggedbottom \hfuzz=2.5pt \vfuzz=10pt
\title{\CusTeX 宏集手册}
\author{Longaster}
\date{\zhtoday\quad v\UseName{cus@versi@n}}
\enablecombinedlist
\begin{document}
\usepagestyle{totalempty}
\setlength{\lineskiplimit}{4pt}
\setlength{\lineskip}{4pt}
\def\thepage{t.\arabic{page}}
\setuplayout{preset=balance}
\maketitle
\frontmatter
\cusdoctoc
\mainmatter
\setuplayout{preset=main}
\usepagestyle{fancy}
\setuptitle[chapter]{numbering=true,pagestyle=fancy}
\removebackground[./watermark]
\chapter{概述}
{\color{red}\bfseries 目前 \CusTeX 还处于早期的开发状态中,很多功能还并不完善。}
\CusTeX (\CusLaTeX)宏集意为 a \textcolor{purple}Chinese \textcolor{purple}User
\textcolor{purple}Scheme \textcolor{purple}\TeX(\textcolor{purple}{\LaTeX}),
为中文 \LaTeX 用户定制的文档类框架。
对于排版外文文档,已经有诸如 \hologo{KOMAScript}、\cls{memoir} 等优秀的文档类,
由于中文文档的特殊性,直接使用它们虽然可能,但这些文档类终究不是为中文用户设计的,
使用起来仍有些不便。
而像 \pkg{ctex} 文档类,则注重解决输出中文的最根本的问题,
要求它们具有像 \hologo{KOMAScript} 文档类的完整功能不太可能。
如此,本宏集应运而生。
使用 \CusTeX 可以方便地设置标题、目录、页面样式(页面几何元素、页眉页脚等)、图表、背景、水印、
边注、脚注、列表、索引、术语表等文档元素,具有强大的可定制性。\CusTeX 原生兼容 \pkg{pgf} 和
\pkg{tcolorbox},加载这两个宏包或使用 \cuslibrary{pgf} 库可实现更多的功能 \TODO。
\CusTeX 通过模块(module)和库(library)来实现诸多功能。其中\emph{模块}是核心部分,
\CusTeX 将自动加载它们;库是提供额外功能的,用户可以选择是否加载它们。库可能依赖其它模块和库,
但模块不会依赖库。
模块和库均可能加载其它宏包,一般情况下,\CusTeX 会自动加载这些模块并处理好它们的依赖和兼容性,
当用户需要加载其它宏包时,最好通过 \CusTeX 的宏包加载机制来加载它们 \TODO。
\CusTeX 支持 \XeLaTeX、\LuaLaTeX、\upLaTeX、\ApLaTeX(p\LaTeX-ng)等多种编译方式,其中
\LuaLaTeX、\upLaTeX、\ApLaTeX 还支持竖排 \TODO。
\CusTeX 还很好的支持和适配了通用驱动(generic driver),这是 \LaTeXe 2022-06-01 中的新功能。
\emph{不}兼容 \pkg{beamer}。
\chapter{文档接口}
\CusTeX 定义的命令有的用于文档中,有的则是面向开发者,本章描述那些在文档中可能使用到的接口。
\begin{function}{\CusTeX,\CusLaTeX}
Logo。输出 \CusTeX,\CusLaTeX。
\end{function}
\begin{function}{\cussetup}
\begin{syntax}
\verb|\cussetup| \marg{key-vals}
\verb|\cussetup| \oarg{key path} \marg{key-vals}
\verb|\cussetup| \{
~~\meta{key path_1} = \marg{key-vals_1} ,
~~\meta{key path_2} = \marg{key-vals_2} ,
~~...
\}
\end{syntax}
键值设置命令。
\CusTeX 的不同模块使用不同的 \meta{key path},一般情况下,这些模块会提供自己的键值设置接口,
为了使用 \cs{cussetup} 来设置这些键值,需要指定 \meta{key path}。
\end{function}
在本文档中,键的说明文字旁的表格中列出了键的完整写法,\meta{key path} 即为灰色的部分。
如键 \keyreflist[frame]{outer-sep,sep} 可以写成
\begin{xample}
\cussetup[frame]{outer-sep=0pt, sep=20pt}
或
\cussetup{ frame/outer-sep=0pt, frame/sep=20pt }
\stopxamplecode
\xamplecode\medskip
\end{xample}
有的键有默认值,就是说,当只写出键,而不写出等号以及后面的值时,自动的使用这个默认值。
默认值一般以加粗字体显示在键的后面,有时也会在键的说明中给出。
初始值是在键定义时就赋给键的值,只执行一次,如果没有修改过这个键,或者只在局部修改它,
那么在其它地方都使用这个初始值。
还有的键会根据其它设置而自动修改,根据实际需要和作用,每个键有可能有特殊的用法,
阅读相应说明即可。
\begin{function}{\cussetstyle}
\begin{syntax}
\verb|\cussetstyle| \oarg{key path} \marg{key} \marg{key-vals}
\verb|\cussetstyle| * \oarg{key path} \marg{key} \marg{code}
\end{syntax}
自定义键。
带 \verb|*| 的可使用一个参数,它代表键传入的值。
\end{function}
例如,若要为 \envref{Framed} 新增键选项,则可以使用此命令。
\begin{xample}
\colorlet{frame color}{black}
\colorlet{fill color}{white}
\cussetstyle*[frame]{frame color}{\colorlet{frame color}{#1}}
\cussetstyle*[frame]{fill color}{\colorlet{fill color}{#1}}
\cussetstyle[frame]{color frame}{%
frame={\setlength{\fboxsep}{#1\cusframesep}%
\setlength{\fboxrule}{#1\cusframerule}%
\fcolorbox{frame color}{fill color}}%
}
\begin{Framed}[frame color=blue, fill color=blue!20, color frame=2]
\zhlipsum[1]
\end{Framed}
\stopxamplecode
\xamplecode\medskip
\end{xample}
本说明文档中,若参数是 \meta{clist} 或 \meta{comma list},则说明该参数是逗号分隔的列表;
若是键值选项,说明参数是逗号分隔的键值选项列表;若是 \meta{list},则一般是普通的记号列表,
如果一项有多个记号,需要把这些记号用 \verb|{}| 括起来。
\section{\cusmodule{ltx}模块}
\cusmodule{ltx} 模块,本模块封装或提供一些 \LaTeXe 的接口。
\begin{function}[EXP]{\csstring}
\begin{syntax}
\V\csstring \meta{cs}
\end{syntax}
提取控制序列 \meta{cs} 的名字。
\end{function}
\begin{xample}
\ttfamily \csstring\CusTeX \quad \csstring\|
\stopxamplecode
\xampleprint
\end{xample}
\begin{function}[EXP]{\Replicate}
\begin{syntax}
\verb|\Replicate| \marg{num expr} \marg{code}
\end{syntax}
重复 \meta{code} \meta{num expr} 次。
\end{function}
\begin{function}{\lo,\hi,\lohi}
\begin{syntax}
\V\lo \marg{material}
\V\hi \marg{material}
\V\lohi \marg{lo material} \marg{hi material}
\end{syntax}
在数学模式中,它们相当于 \verb|{}_{...}|、\verb|{}^{...}|、\verb|_{...}^{...}|,
在文本模式中,它们也可直接使用,\cs{lo} 相当于 \tn{textsubscript},
\cs{hi} 相当于 \tn{textsuperscript}。
\end{function}
\begin{xample}
\Large 字\lo{下}\hi{上},字\lohi{下}{上}。$ H\lo{u}\hi{n} H\lohi{u}{n}$.
\stopxamplecode
\xampleprint
\end{xample}
\begin{function}{\makelapbox,\parlapbox}
\begin{syntax}
\V\makelapbox \marg{text}
\V\makelapbox \oarg{width} \oarg{pos} \marg{text}
\V\makelapbox \oarg{width} \oarg{pos} \oarg{lap to} \marg{text}
\V\parlapbox \marg{width} \marg{text}
\V\parlapbox \oarg{pos} \oarg{height} \oarg{inner-pos} \marg{width} \marg{text}
\V\parlapbox \oarg{pos} \oarg{height} \oarg{inner-pos} \oarg{lap to} \marg{width} \marg{text}
\end{syntax}
\cs{makelapbox} 的用法和 \tn{makebox} 一样,但是会把它向 \meta{lap to} 侧重叠。
若给出了 \meta{width} 或它不为空,则先把 \meta{text} 放在宽为 \meta{width} 的盒子中。
\meta{pos} 可选值为 \UseList[\texttt]{lcr}{、},
分别表示把 \meta{text} 放在盒子的左边、中间、右边,默认值为 \texttt{c}。
\meta{lap to} 的可选值为 \UseList[\texttt]{lcr}{、},
分别表示把 \meta{text}(如果有 \meta{width},则是把宽为 \meta{width} 的盒子)嵌入
到左、右的文字中或一半嵌入到左边一半嵌入到右边,\meta{lap to} 的默认值为 \meta{pos} 的值。
\cs{parlapbox} 的用法和 \tn{parbox} 一样,但是会把它向 \meta{lap to} 侧重叠。
\meta{pos} 指定基线的位置,可选值为 \UseList[\texttt]{tcb}{、},
分别表示第一行文字的基线位置、文字的中间以及末行文字的基线。的默认值为 \texttt{c}。
若给出 \texttt{height},则把文字放在高度为 \texttt{height} 的盒子中,
根据 \meta{inner-pos} 来决定文字的垂直位置,可选值为 \UseList[\texttt]{tcb}{、}。
\end{function}
\begin{xample}
这里\makelapbox{是}文字。
这里\makelapbox[][l]{是}文字。
这里\makelapbox[][r]{是}文字。
\stopxamplecode
\xampleprint
\end{xample}
\begin{function}[rEXP]{\numberfixedwidth,\numerzerofill}
\begin{syntax}
\V\numberfixedwidth \marg{width} \marg{filler} \marg{printer} \marg{number}
\V\numberzerofill \marg{width} \marg{number}
\end{syntax}
先将 \meta{printer} 作用于 \meta{number},然后用 \meta{filler} 向左或向右填充,
填充 \meta{filler} 的次数为 $\veta{width}-\mathrm{len}(\veta{printer}(\meta{number}))$。
当 \meta{width} 小于 0 时,在右边填充,否则在左边填充。
\meta{printer} 必须是可展的。
\cs{numberzerofill} 用 0 填充数字。
\end{function}
\begin{xample}
\ExplSyntaxOn
\numberfixedwidth { 6 } { 0 } { \int_to_Hex:n } { 42 } \quad
\numberfixedwidth { 6 } { 0 } { \int_to_Hex:n } { `好 } \quad
\numberzerofill { 6 } { 12478 }
\ExplSyntaxOff
\stopxamplecode
\xampleprint
\end{xample}
\begin{function}{\zkern}
相当于 \verb|\kern 0pt\relax|。
\end{function}
\begin{function}[type=environment]{enumlist,enumlist*}
\begin{syntax}
\verb|\begin{enumlist}| \oarg{default label} \marg{left} \marg{indent} \marg{label sep} \marg{right}
~~~~...
\verb|\end{enumlist}|
\end{syntax}
相当于 \env{list} 环境。
\meta{default label} 为列表的标签,默认为空;\meta{left} 为左侧间距;
\meta{indent} 为每段首行的缩进;\meta{label sep} 为标签与首行的间距;
\meta{right} 为右侧间距。
带星号的环境还会设置段落间距和每项的间距为 0pt。
\end{function}
\begin{function}{\cusemoji,\cusemojitotalratio,\cusemojilowerratio}
\begin{syntax}
\V\cusemoji \marg{pic filename}
\end{syntax}
插入一张图片,它的(总)高度为当前文字的高度的 \cs{cusemojitotalratio} 倍,
并向下移动 \cs{cusemojilowerratio} 个文字的高度。
\cs{cusemojitotalratio} 和 \cs{cusemojilowerratio}
必须为 \texttt{0} 或 \veta{a}\texttt/\veta{b},其中 \veta{a}、
\veta{b} 为非零整数。
\cs{cusemojitotal\-ratio} 默认为 \texttt{8/9},如果是负数则上下翻转,但宽度也会变成负值。
\cs{cusemoji\-lowerratio} 默认为 \texttt{1/7},如果是负数则向上移动。
可以用于数学模式,会根据是否处于上下标而改变大小。
需要用户自行加载 \pkg{graphicx} 宏包。
\end{function}
\begin{xample}
\newcommand{\bdhj}{\cusemoji{bd-huaji.png}}
滑稽 \bdhj ; $ \sin\bdhj = 2^\bdhj $
\stopxamplecode
\xampleprint
\end{xample}
\begin{function}{\IfGraphicsExists}
\begin{syntax}
\V\IfGraphicsExists \marg{graphics name} \marg{true code} \marg{false code}
\end{syntax}
判断图片文件是否存在。\tn{@curr@file} 展开为此文件名,若无此文件则为 \tn{relax}。
它会自动查找 \tn{setgraphicspath} 设置的路径,且可以自动补全文件扩展名。
需要用户自行加载 \pkg{graphicx} 宏包。
\end{function}
\begin{function}{\InputIfGraphicsExists}
\begin{syntax}
\V\InputIfGraphicsExists * \oarg{key-val list} \marg{file}
\end{syntax}
如果图片存在时使用图片,否则什么也不做。
它会自动查找 \tn{setgraphicspath} 设置的路径,且可以自动补全文件扩展名。
需要用户自行加载 \pkg{graphicx} 宏包。
\end{function}
\begin{function}{\setinputpath,\setgraphicspath}
\begin{syntax}
\V\setinputpath \marg{path clist}
\V\setinputpath + \marg{path clist}
\V\setgraphicspath \marg{path clist}
\V\setgraphicspath + \marg{path clist}
\end{syntax}
设置导入文件或导入图片时需要查找的路径。\meta{path clist} 使用逗号分隔,
且需使用 \texttt/ 作为目录分隔符。带 \texttt+ 的命令为附加到原有的设置之后。
使用 \tn{setgraphicspath} 时需要自行加载 \pkg{graphicx} 宏包。
\end{function}
\subsection{参数处理器,Argument processors}
\pkg{ltcmd} 提供了 \cs{NewDocumentCommand} 等命令来定义新的命令,每个参数可以使用
“参数处理器”来先行处理,再传递给实际的代码(或其它参数处理器),并提供了 \cs{Reverse\-Bool\-ean}、
\cmd\SplitArgument、\cmd\SplitList、\cs{TrimSpaces} 等几个参数处理器。
本模块提供了更多的处理器。
\begin{function}{\ReplaceArgumentIf}
\begin{syntax}
\V\ReplaceArgumentIf \marg{test function} \marg{true replacement} \marg{false replacement}
\end{syntax}
\meta{test function} 需要三个参数,分别为要测试的值、true 分支、false 分支。
当测试为真时,把参数替换为 \meta{true replacement},否则,替换为 \meta{false replacement}。
\end{function}
\begin{xample}
\newcommand\mytestfake[3]{\ifthenelse{\equal{#1}{fake}}{#2}{#3}}
%\usepackage{ifthen}
\DeclareDocumentCommand\whatnews
{ >{ \ReplaceArgumentIf{\mytestfake}{true}{#1} } m }
{#1 news}
\whatnews{fake}, \whatnews{some}.
\stopxamplecode
\xampleprint
\end{xample}
上述代码定义了一个命令 \verb|\whatnews|,它检查第一个参数是否为 \verb|fake|,如果是,
则替换为 \verb|true|。
\begin{function}{\ReplaceArgumentIfEqual,\ReplaceArgumentIfStrEqual}
\begin{syntax}
\V\ReplaceArgumentIfEqual \marg{tl} \marg{true replacement} \marg{false replacement}
\V\ReplaceArgumentIfStrEqual \marg{str} \marg{true replacement} \marg{false replacement}
\end{syntax}
判断参数是否等于 \meta{tl}(或 \meta{str}),如果是则替换为 \meta{true replacement},否则,
替换为 \meta{false replacement}。
\end{function}
\begin{xample}
\DeclareDocumentCommand\foo
{ >{ \ReplaceArgumentIfEqual{s}{c}{#2} } m
>{ \ReplaceArgumentIfEqual{j}{m}{#2} } m }
{[#1][#2]}
\foo {k}{j}
\foo {s}{o}
\stopxamplecode
\xampleprint
\end{xample}
上述代码定义了一个命令 \verb|\foo|,它判断第一个参数是否为 \verb|s|,如果是,
则替换为 \verb|c|,否则替换为第二个参数的值(在使用它的参数处理器之前的值)。
判断第二个参数是否为 \verb|j|,如果是则替换为 \verb|m|,否则不变。
\begin{function}{\ReplaceArgumentIfMatch}
\begin{syntax}
\V\ReplaceArgumentIfMatch \marg{regex} \marg{true replacement} \marg{false replacement}
\end{syntax}
判断此参数是否匹配正则表达式 \meta{regex},如果是,则替换为 \meta{true replacement},
否则,替换为 \meta{false replacement}。
\end{function}
\begin{function}{\ExpandArgument}
\begin{syntax}
\V\ExpandArgument \marg{spec}
\end{syntax}
类似于 \cs{ExpandArgs},先使用 \meta{spec} 指定的展开方式展开这个参数,再传递给实际的代码(或其它参数处理器)。
目前有效的 \meta{spec} 为 \verb|coVvefx| 和 \verb|p| 之一。前几个和 \cs{ExpandArgs}
的类似,\verb|p| 类似于 \verb|x|,但那些被保护的命令和未定义的命令以及
数学公式中的命令不会被展开。
此外,还有几个特殊的 spec:
\begin{itemize}
\item[\texttt{sS}] --- 把参数转化为字符串,(使用 \tn{detokenize});
\item[\texttt{sX}] --- 和 \verb|p| 完全一样,(使用 \cs{text_expand:n});
\item[\texttt{sF}] --- 类似于 \verb|x|,但不可展开的记号和未定义的命令被移除了,(使用 \cs{text_purify:n});
\item[\texttt{sP}] --- 类似于 \verb|sX|,速度更快,但数学公式中的命令会被展开,未定义的命令也会出错。
\end{itemize}
\end{function}
\begin{xample}
\DeclareDocumentCommand \faa
{ >{\ExpandArgument{p}} m }{#1}
\DeclareDocumentCommand \fee
{ >{\ExpandArgument{sS}} >{\ExpandArgument{p}} m }{#1}
\DeclareDocumentCommand \fii
{ >{\ExpandArgument{sS}} >{\ExpandArgument{sP}} m }{#1}
\DeclareDocumentCommand \foo
{ >{\ExpandArgument{sS}} >{\ExpandArgument{sF}} m }{#1}
\newcommand{\mytextit}[1]{\textit{#1}}
\faa{\textbf{bfseries} \mytextit{itshape} $ \mytextit{math rm } a+b=c $}\par
\ttfamily
\fee{\textbf{bfseries} \mytextit{itshape} $ \mytextit{math rm } a+b=c $}\par
\fii{\textbf{bfseries} \mytextit{itshape} $ \mytextit{math rm } a+b=c $}\par
\foo{\textbf{bfseries} \mytextit{itshape} $ \mytextit{math rm } a+b=c $}\par
\stopxamplecode
\xampleprint
\end{xample}
\begin{xample}
\DeclareDocumentCommand\oof
{ >{ \ReplaceArgumentIfMatch{\A.\Z}{0#1}{#1} } >{ \ExpandArgument{e} } m
>{ \ReplaceArgumentIfMatch{(.{2,}|[^lcr])}{c}{#2} } m }
{[#1][#2]}
\oof {1}{m}
\oof {10}{mn}
\oof {jk}{r}
\oof {{jk}}{r}
\DeclareDocumentCommand\mytext{}{ab}% 不能被展开
\oof {\mytext}{m}
\DeclareExpandableDocumentCommand\mytext{}{ab}% 可以被展开
\oof {\mytext}{m}
\stopxamplecode
\xampleprint
\end{xample}
上述代码定义了一个命令 \verb|\oof|,它的第一个参数先被完全展开
(使用 \cs{Exp\-and\-Argument}),
再传递给后一个参数处理器,这个参数处理器判断此参数是否是单个记号,如果是,则在其左侧加上
\verb|0|,否则保持不变。
它的第二个参数使用正则表达式 \verb!(.{2,}|[^lcr])! 进行判断,如果匹配则替换为 \verb|c|,
否则保持不变。
\begin{function}{\RegexReplaceArgument}
\begin{syntax}
\V\RegexReplaceArgument \marg{regex} \marg{regex replacement}
\V\RegexReplaceArgument + \marg{regex} \marg{regex replacement}
\end{syntax}
在参数中使用 \meta{regex} 查找,并用 \meta{replacement} 替换之。
带 \texttt{+} 的替换所有,不带 \texttt{+} 的替换一次。
\end{function}
\begin{xample}
\DeclareDocumentCommand\foo
{ >{ \RegexReplaceArgument
{(\d{2,4})[\/\-](\d{1,2})[\/\-](\d{1,2})}
{\1/\2/\3}
}
m }
{#1}
\foo{1920/02/09}
\foo{1920-02-09}
\stopxamplecode
\xampleprint
\end{xample}
\begin{texnote}
以上这些正则表达式的匹配和替换使用的是 \LaTeXiii 的 \texttt{l3regex} 库中的命令,
如 \cs{regex_match:nnTF}、\cs{regex_replace_once:nnN}、\cs{regex_replace_all:nnN},
支持的正则表达式语法请参考 \file{interface3.pdf}。
\end{texnote}
\begin{keyval}[path=typo]{special-dischyph,dischyph-opacity}
\begin{syntax}
special-dischyph = <&normal|opacity|none>
dischyph-opacity = <{0--1之间的数}>
\end{syntax}
\verb|special-dischyph| 可以让 \tn{-} (和 \tn{@dischyph})显示的文字具有透明度。
\opt{normal} 为默认的显示效果。\opt{none} 移除显示的字符。
\opt{dischyph-opacity} 设置透明度,但不会直接修改 \opt{special-dischyph}。
使用 \cs{DocumentMetadata} 后效果更好。
\end{keyval}
\section{\cusmodule{util}模块}
\nofuncskip
\begin{function}[rEXP]{\MapClist,\MapList,\MapInteger}
\begin{syntax}
\V\MapClist \marg{comma list} \marg{tokens}
\V\MapList \marg{list} \marg{tokens}
\V\MapInteger \oarg{initial value} \oarg{step} \marg{final value} \meta{function}
\end{syntax}
\cs{MapClist} 使用 \meta{tokens} 迭代逗号分隔的列表 \meta{comma list},
它将 \meta{tokens} 置于列表项之前。
\cs{MapList} 使用 \meta{tokens} 迭代记号列表 \meta{list},它将 \meta{tokens} 置于列表项之前。
\cs{MapInteger} 从 \meta{initial value} 到 \meta{final value} 以 \meta{step} 为步长,
来迭代 \meta{function}。
\end{function}
\begin{function}{\IterateClist,\IterateList,\IterateInteger}
\begin{syntax}
\V\IterateClist \marg{comma list} \marg{inline code}
\V\IterateList \marg{list} \marg{inline code}
\V\IterateInteger \oarg{initial value} \oarg{step} \marg{final value} \marg{inline code}
\end{syntax}
\cs{IterateClist} 使用 \meta{inline code} 迭代逗号分隔的列表 \meta{comma list},\meta{inline code} 可带一个参数 \verb|#1|,它为当前迭代项。
\cs{IterateList} 使用 \meta{inline code} 迭代记号列表 \meta{list},\meta{inline code} 可带一个参数 \verb|#1|,它为当前迭代项。
\cs{IterateInteger} 从 \meta{initial value} 到 \meta{final value} 以 \meta{step} 为步
长,来迭代 \meta{inline code},\meta{inline code} 可以带一个参数 \verb|#1|,它为当前整数。
\end{function}
\begin{xample}
$ \MapClist{1,2,3,n}{a_} $ \quad $ \IterateClist{1,2,3}{a_{#1}+} a_n $
\stopxamplecode
\xampleprint
\end{xample}
\begin{function}{\IterateThread}
\begin{syntax}
\verb|\IterateThread| \marg{comma list_1} \marg{comma list_2} \marg{inline code}
\verb|\IterateThread| * \marg{comma list_1} \marg{comma list_2} \marg{inline code}
\verb|\IterateThread| \oarg{n} \marg{comma list_1} ... \marg{comma list_n} \marg{inline code}
\verb|\IterateThread| * \oarg{n} \marg{comma list_1} ... \marg{comma list_n} \marg{inline code}
\verb|\IterateThread| \oarg{n} \marg{comma list_1} ... \marg{comma list_n}
~~~~~~~~~~~~~~~~~\oarg{middle} \marg{inline code}
\verb|\IterateThread| \oarg{n} \marg{comma list_1} ... \marg{comma list_n}
~~~~~~~~~~~~~~~~~\oarg{middle} \oarg{last} \marg{inline code}
\verb|\IterateThread| * \oarg{n} \marg{comma list_1} ... \marg{comma list_n}
~~~~~~~~~~~~~~~~~\oarg{middle} \oarg{last} \marg{inline code}
\end{syntax}
使用 \meta{inline code} 迭代这 $n$ 个 \meta{comma list},\meta{inline code}
可接受 $n+1$ 个参数,其中第一个参数为索引,其后的参数分别为诸列表的当前迭代项。
当某一个列表结束时迭代终止,多余的项被移除。$n$ 的可选值为 1 -- 7,即最多可使用 7 个列表。
使用 \meta{middle} 来分隔各项,最后两项用 \meta{last} 分隔,默认与 \meta{middle} 一致。如未给出,则为空,即不在两项之间插入其它符号。
带 \verb|*| 的版本保留空项和每项前后的空格,不带 \verb|*| 的则不保留。
若某个 \meta{comma list} 为单个记号,则将其展开一次。这样,可以使用一个宏保存列表项。
\end{function}
\begin{xample}
$ \IterateThread{a+b,c+d,e+f}{A+B,C+D,E+F}{\dfrac{#2}{#3}\geq} 0 $ \par
$ \IterateThread {a+b, ,e+f}{A+B,C+D, }{\dfrac{#2}{#3}\geq} 0 $ \par
$ \IterateThread *{a+b, ,e+f}{A+B,C+D, }{\dfrac{#2}{#3}\geq} 0 $ \par
\stopxamplecode
\xamplecode
\xampleline\par\smallskip
\xampletext
\end{xample}
\begin{xample}
$ \IterateThread[2]{1,2,3,n}{n,n-1,n-2,1}[+][+\cdots+]{a_{#2}\cdot b^{#3}} $
%= $ a_1\cdot b^n+a_2\cdot b^{n-1}+a_3\cdot b^{n-2}+\cdots+a_n\cdot b^1 $
\stopxamplecode
\xampleprint
\end{xample}
\begin{function}[EXP]{\UseList,\UseClist}
\begin{syntax}
\V\UseList \marg{token list} \marg{separator}
\V\UseList \oarg{function} \marg{token list} \oarg{final two separator} \marg{separator}
\V\UseClist \marg{comma list} \marg{separator}
\V\UseClist \oarg{function} \marg{comma list} \oarg{final two separator} \marg{separator}
\end{syntax}
把 \meta{separator} 插入到 \meta{token list}(或 \meta{comma list})中间。
\meta{function} 会应用到 \meta{token list}(\meta{comma list})的每一项。
当只有两项时,这两项中间会使用 \meta{final two separator};
最后两项之间也会使用 \meta{final two separator},其它情况的项中间使用 \meta{separator}。
\end{function}
\begin{xample}
\UseList[\texttt]{abc}{、}。
\UseList[\texttt]{ab}[和]{、}。
\UseList[\texttt]{abcd}[和]{、}。
\UseClist[\texttt]{a,b,c}{、}。
\UseClist[\texttt]{a,b}[和]{、}。
\UseClist[\texttt]{a,b,c,d}[和]{、}。
\stopxamplecode
\xampleprint
\end{xample}
\begin{function}[rEXP]{\ucchar,\ucchars}
\begin{syntax}
\verb|\ucchar| \marg{unicode slot}
\verb|\ucchars| \marg{unicode slots}
\end{syntax}
展开为 \meta{unicode slot} 对应的 Unicode 字符。\meta{unicode slots} 为空格分隔的
Unicode 代码点。
\end{function}
\begin{xample}
\ucchar{"5982}:%
\ucchars{"75 "74 "69 "6C "6A21 "5757}。
\stopxamplecode
\xampleprint
\end{xample}
\begin{function}{\Verbatimize}
\begin{syntax}
\verb|\Verbatimize| \marg{balanced tokens}
\verb|\Verbatimize| * \meta{token} \meta{tokens} \meta{token}
\end{syntax}
以 verbatim 的形式输出 \meta{balanced tokens} 或 \meta{tokens}。
带 \verb|*| 的版本作用与 \tn{verb} 类似,由一对 \meta{token} 包裹,也支持一对 \verb|{ }| 包裹。只是它仍然使用当前字体。不能作为一个命令的参数。
不带 \verb|*| 的版本可以作为另一个命令的参数,但如下几个字符必须使用转义的形式:
\texttt{\Verbatimize{\#\$\%\ \{\}\\\^}},即,使用 \verb|\#\$\%\ \{\}\\\^|。
\end{function}
\begin{function}{\IfPageOdd,\IfAbsPageOdd}
\begin{syntax}
\verb|\IfPageOdd| \marg{true} \marg{false}
\end{syntax}
判断当前页码是否为奇数。\cs{IfAbsPageOdd} 仅在 shipout 时有效(如在 \hook{shipout/\allowbreak foreground},\hook{shipout/background},\hook{shipout},
\hook{shipout/after} 钩子中)。
平常使用时并不一定准确,\cusmodule{ref} 库改进了这一点,见\cref{sec:lib-ref}。
\end{function}
\begin{function}[EXP]{\@ifpageodd,\@ifabspageodd}
同上,但可展。
\end{function}
\section[float-barrier=on]{页面布局,\cusmodule{layout}模块}
\cusmodule{layout} 提供页面布局的相关接口。
\begin{function}{\setuplayout}
\begin{syntax}
\verb|\setuplayout| \;\marg{layout key-val}
\verb|\setuplayout| \oarg{preset name} \marg{layout key-val}
\verb|\setuplayout| * \oarg{preset name} \marg{layout key-val}
\end{syntax}
设置布局。
第一个用法为直接设置页面布局。
第二个除了设置布局外,还将这个布局保存下来,可供后续重复使用。
第三个则仅保存布局,而不设置这个布局。
可以在文档中间改变布局,纸张大小也可改变。
\end{function}
% from geometry.dtx
\def\gpart#1{\textsf{\textsl{\color[rgb]{.0,.45,.7}#1}}}
% \thisfloatsetup{margins=hangoutside,capposition=beside,
% capbesideposition={top,inside},floatwidth=\textwidth}
\begin{figure}
\IfPageOdd{\raggedleft}{\raggedright}\small
{\unitlength=.65pt
\begin{picture}(450,250)(0,-10)
\put(20,0){\framebox(170,230){}}
\put(20,235){\makebox(170,230)[br]{\gpart{paper}}}
\begingroup\thicklines
\put(40,30){\framebox(120,170){}}\endgroup
\put(40,30){\makebox(120,165)[tr]{\gpart{total body}~}}
\put(45,30){\makebox(0,170)[l]{\texttt{height}}}
\put(40,35){\makebox(120,0)[bc]{\texttt{width}}}
\put(50,-20){\makebox(120,0)[bc]{\texttt{paperwidth}}}
\put(10,45){\makebox(0,170)[r]{\texttt{paperheight}}}
\put(90,200){\makebox(0,30)[lc]{\texttt{top}}}
\put(90,0){\makebox(0,30)[lc]{\texttt{bottom}}}
\put(10,70){\makebox(0,0)[r]{\texttt{left}}}
\put(10,55){\makebox(0,0)[r]{(\texttt{inner})}}
\put(200,70){\makebox(0,0)[l]{\texttt{right}}}
\put(200,55){\makebox(0,0)[l]{(\texttt{outer})}}
\put(80,230){\vector(0,-1){30}}\put(80,30){\vector(0,-1){30}}
\put(80,200){\vector(0,1){30}}\put(80,0){\vector(0,1){30}}
\put(20,70){\vector(1,0){20}}\put(40,70){\vector(-1,0){20}}
\put(160,70){\vector(1,0){30}}\put(190,70){\vector(-1,0){30}}
\multiput(160,30)(5,0){24}{\line(1,0){2}}
\multiput(160,200)(5,0){24}{\line(1,0){2}}
\begingroup\thicklines
\put(280,30){\framebox(120,170){}}\endgroup
\put(283,133){\makebox(0,12)[l]{\texttt{textheight}}}
\put(295,130){\vector(0,-1){100}}\put(295,150){\vector(0,1){50}}
\multiput(280,220)(5,0){24}{\line(1,0){3}}
\put(280,208){\makebox(120,20)[bc]{\gpart{head}}}
\multiput(280,207)(5,0){24}{\line(1,0){3}}
\put(420,225){\makebox(0,0)[l]{\texttt{headheight}}}
\put(418,225){\line(-2,-1){20}}
\put(420,213){\makebox(0,0)[l]{\texttt{headsep}}}
\put(418,213){\line(-2,-1){20}}
\put(420,12){\makebox(0,0)[l]{\texttt{footskip}}}
\put(418,12){\line(-2,1){20}}
\put(280,40){\makebox(120,140)[c]{\gpart{body}}}
\put(305,45){\vector(-1,0){25}}\put(375,45){\vector(1,0){25}}
\put(80,230){\vector(0,-1){30}}\put(80,30){\vector(0,-1){30}}
\put(280,48){\makebox(120,0)[c]{\texttt{textwidth}}}
\put(280,15){\makebox(120,10)[c]{\gpart{foot}}}
\multiput(280,14)(5,0){24}{\line(1,0){2}}
\put(410,30){\dashbox{3}(30,170){}}
\put(415,30){\makebox(30,170)[l]{\gpart{marginal note}}}
\put(425,45){\vector(-1,0){15}}\put(425,45){\vector(1,0){15}}
\put(450,70){\makebox(0,0)[l]{\texttt{marginparsep}}}
\put(448,70){\line(-3,-1){43}}
\put(450,45){\makebox(0,0)[l]{\texttt{marginparwidth}}}
\end{picture}}
\caption{长度变量}
\label{fig:layout}
\end{figure}
键值接口大都直接使用 \pkg{geometry} 宏包的接口。具体用法说明可参见其说明文档。如未作说明,
则与 \pkg{geometry} 宏包提供的接口用法相同。
\subsection{页面尺寸}
\nofuncskip
\begin{keyval}[path=layout]{papername,paper}
\begin{syntax}
papername|paper = \marg{papername}
\end{syntax}
设置纸张大小。\meta{papername} 为预定义的纸张名,大小写无关。
\end{keyval}
\begin{table}[tb]
\IfPageOdd{\makebox[\linewidth][l]}{\makebox[\linewidth][r]}%
{\includegraphics{tab-defined-papername}}
\caption{预定义的纸张名}\label{tab:defined-papername}
\end{table}
\begin{keyval}[path=layout]{papersize,paperwidth,paperheight}
\begin{syntax}
papersize = \{\meta{宽},\meta{高}\} 或 \{\meta{宽}:\meta{高}\} 或 \marg{长度}
paperwidth = \marg{宽}
paperheight = \marg{高}
\end{syntax}
设置纸张大小。
\end{keyval}
\begin{keyval}[path=layout]{paperorientation,orientation,landscape,portrait,direction}
\begin{syntax}
paperorientation|orientation = <&landscape|portrait>
landscape &&
portrait &&
direction = <&bigwidth|bigheight|normal|inverse>
\end{syntax}
设置纸张方向。使用 \opt{portrait} 时,纸张高度大于宽度。\opt{landscape} 则反之。
\opt{direction} 的 \opt{bigheight} 和 \opt{normal} 相当于 \opt{portrait},
\opt{bigwidth} 和 \opt{inverse} 相当于 \opt{landscape}。
使用 \opt{papername} 等选项时,将自动设置纸张方向,使得实际纸张宽高与所给一致。
\end{keyval}
\begin{keyval}[path=layout]{layout,layoutname,
layoutwidth,layoutheight,layoutsize,
layouthoffset,layoutvoffset,layoutoffset,centerlayout}
设置 \gpart{layout} 部分大小。
\opt{layout} 或 \opt{layoutname} 会根据纸张方向自动交换长宽,因此纸张方向必须先于它们设置。
\opt{centerlayout} 通过将 \opt{layoutfoffset} 和 \opt{layoutvoffset}
设置为合适的值,以将
\gpart{layout} 部分置于纸张中心。
见 \pkgdoc{geometry}。
\end{keyval}
\begin{function}{\layoutwidth,\layoutheight,
\layoutloffset,\layouttoffset,\layoutroffset,\layoutboffset}
\gpart{layout} 的大小,以及距离纸张左、上、右、下侧的长度。在 \TikZ 中使用时可能需要用
\tn{the} 获取它们的值,
使用 \cs{dimeval}、\tn{dimexpr} 等命令以及 \pkg{calc} 宏包的功能时则不需要。
若是设置了 \opt{twoside},它们\emph{不会}自动切换左侧和右侧的值。
\end{function}
\subsection{主体尺寸}
此小节与 \pkg{geometry} 对应部分的用法和作用相同。
\begin{keyval}[path=layout]{hscale,vscale,scale}
\begin{syntax}
hscale = \marg{正实数} & 0.7
vscale = \marg{正实数} & 0.7
scale = \{\meta{hscale},\meta{vscale}\} 或 \marg{正实数}
\end{syntax}
设置 \gpart{total part} 部分的宽高与 纸张宽高的比率。
\end{keyval}
\begin{keyval}[path=layout]{totalwidth,width,totalheight,height,total}
\begin{syntax}
totalwidth |width = \marg{长度}
totalheight|height = \marg{长度}
total = \{\meta{totalwidth},\meta{totalheight}\} 或 \marg{长度}
\end{syntax}
设置 \gpart{total part} 部分的宽高。
\end{keyval}
\begin{keyval}[path=layout]{textwidth,textheight,body,text}
\begin{syntax}
textwidth = \marg{长度}
textheight = \marg{长度}
body = \{\meta{textwidth},\meta{textheight}\}
text = \marg{长度}
\end{syntax}
设置 \tn{textwidth}、\tn{textheight},即 \gpart{body} 部分的宽高。
\end{keyval}
\begin{keyval}[path=layout]{lines}
\begin{syntax}
lines = \marg{行数}
\end{syntax}
根据 \meta{行数} 设置 \opt{textheight}。\meta{行数} 一般为正整数。
\end{keyval}
\begin{keyval}[path=layout]{includehead,includefoot,
includeheadfoot,includehf}
\begin{syntax}
includehead = <&\TTF> & false
includefoot = <&\TTF> & false
includeheadfoot|includehf = <&\TTF>
\end{syntax}
控制是否将页眉(\tn{headheight}、\tn{headsep})、页脚(\tn{footskip})
计入 \gpart{total part} 部分中。
\end{keyval}
\begin{keyval}[path=layout]{includemarginpar,includemp}
\begin{syntax}
includemarginpar|includemp = <&\TTF> & false
\end{syntax}
控制是否将旁注(\tn{marginparwidth}、\tn{marginparsep})计入 \gpart{body} 部分中。
\end{keyval}
\begin{keyval}[path=layout]{includeall}
\begin{syntax}
includeall = <&\TTF> & false
\end{syntax}
设置 \opt{includeheadfoot} 及 \opt{includemarginpar}。
\end{keyval}
\begin{keyval}[path=layout]{ignorehead,ignorefoot,
ignoreheadfoot,ignorehf}
\begin{syntax}
ignorehead = <&\TTF> & false
ignorefoot = <&\TTF> & false
ignoreheadfoot|ignorehf = <&\TTF>
\end{syntax}
在计算垂直方向的尺寸时,不考虑页眉、页脚。但不修改页眉页脚的尺寸。
\end{keyval}
\begin{keyval}[path=layout]{ignoremarginpar,ignoremp}
\begin{syntax}
ignoremarginpar|ignoremp = <&\TTF> & false
\end{syntax}
在计算水平方向的尺寸时,不考虑旁注的尺寸。但不修改旁注的尺寸。
\end{keyval}
\begin{keyval}[path=layout]{ignoreall}
\begin{syntax}
ignoreall = <&\TTF> & false
\end{syntax}
设置 \opt{ignoreheadfoot} 及 \opt{ignoremarginpar}。
\end{keyval}
\begin{keyval}[path=layout]{heightrounded}
\begin{syntax}
heightrounded = <&\TTF> & false
\end{syntax}
如果设置为真,则将 \opt{textheight} 设置为不小于原 \opt{textheight} 且满足关系:
\[ n\times{}\text{\tn{baselineskip}}{}+{}\text{\tn{topskip}}\]
的最小值。
\end{keyval}
% from geometry.dtx
\thisfloatsetup{margins=hangoutside,capposition=beside,
capbesideposition={top,outside},floatwidth=\textwidth}
\begin{figure}[htb]
\centering\small
{\unitlength=.65pt
\begin{picture}(460,525)(0,0)
\put( 20,310){\framebox(120,170){}}
\put( 20,507){\makebox(120,0)[bl]%
{\textbf{(a)}~\opt{includeheadfoot}}}
\put( 20,460){\line(1,0){120}}\put( 20,450){\line(1,0){120}}
\put( 20,330){\line(1,0){120}}
\put( 20,485){\makebox(120,0)[br]{\gpart{total body}}}
\put( 20,335){\makebox(120,0)[bc]{\texttt{textwidth}}}
\put(150,470){\makebox(0,0)[l]{\texttt{headheight}}}
\put(150,450){\makebox(0,0)[l]{\texttt{headsep}}}
\put(150,390){\makebox(0,0)[l]{\texttt{textheight}}}
\put(150,320){\makebox(0,0)[l]{\texttt{footskip}}}
\put( 10,460){\makebox(120,20)[bc]{\gpart{head}}}
\put( 10,320){\makebox(120,140)[c]{\gpart{body}}}
\put( 10,310){\makebox(120,10)[c]{\gpart{foot}}}
\put(250,310){\framebox(120,170){}}
\put(250,507){\makebox(120,0)[bl]%
{\textbf{(b)}~\opt{includeall}}}
\put(250,460){\line(1,0){95}}\put(250,450){\line(1,0){95}}
\put(250,330){\line(1,0){95}}\put(345,330){\line(0,1){120}}
\put(350,330){\line(0,1){120}}\put(350,450){\line(1,0){20}}
\put(350,330){\line(1,0){20}}
\put(250,485){\makebox(120,0)[br]{\gpart{total body}}}
\put(250,460){\makebox(95,20)[bc]{\gpart{head}}}
\put(250,320){\makebox(95,140)[c]{\gpart{body}}}
\put(385,390){\makebox(95,0)[cl]%
{\gpart{\shortstack[l]{marginal\\note}}}}
\put(250,310){\makebox(95,10)[c]{\gpart{foot}}}
\put(250,335){\makebox(95,0)[bc]{\texttt{textwidth}}}
\multiput(360, 390)(4,0){6}{\line(1,0){2}}
\multiput(348,333)(0,-4){12}{\line(0,1){2}}
\multiput(360,333)(0,-4){8}{\line(0,1){2}}
\put(355,292){\makebox(0,0)[bl]{\texttt{marginparwidth}}}
\put(345,275){\makebox(0,0)[bl]{\texttt{marginparsep}}}
\put( 20, 40){\framebox(120,170){}}
\put( 20,237){\makebox(120,0)[bl]%
{\textbf{(c)}~\opt{includefoot}}}
\put( 20, 60){\line(1,0){120}}
\put( 20,215){\makebox(120,0)[br]{\gpart{total body}}}
\put(150,130){\makebox(0,0)[l]{\texttt{textheight}}}
\put(150, 50){\makebox(0,0)[l]{\texttt{footskip}}}
\put( 20, 50){\makebox(120,160)[c]{\gpart{body}}}
\put( 20, 40){\makebox(120,10)[c]{\gpart{foot}}}
\put( 20, 65){\makebox(120,10)[c]{\texttt{textwidth}}}
\put(250, 40){\framebox(120,170){}}
\put(250,237){\makebox(120,0)[bl]%
{\textbf{(d)}~\opt{includefoot}, \opt{includemp}}}
\put(250, 60){\line(1,0){95}}\put(350, 60){\line(1,0){20}}
\put(250,215){\makebox(120,0)[br]{\gpart{total body}}}
\put(250, 50){\makebox(95,160)[c]{\gpart{body}}}
\put(385,130){\makebox(95,0)[cl]%
{\gpart{\shortstack[l]{marginal\\note}}}}
\put(250, 40){\makebox(95,10)[c]{\gpart{foot}}}
\put(250, 65){\makebox(95,0)[bc]{\texttt{textwidth}}}
\put(345, 60){\line(0,1){150}}\put(350, 60){\line(0,1){150}}
\multiput(360, 130)(4,0){6}{\line(1,0){2}}
\multiput(348, 63)(0,-4){12}{\line(0,1){2}}
\multiput(360, 63)(0,-4){8}{\line(0,1){2}}
\put(355,22){\makebox(0,0)[bl]{\texttt{marginparwidth}}}
\put(345, 5){\makebox(0,0)[bl]{\texttt{marginparsep}}}
\end{picture}}
\captionsetup{labelsep=newline}
\caption[不同模式下的 total part]{\small
\IfLabelOdd{fig:geometry-modes}{\raggedright}{\raggedleft}%
不同模式下的 \gpart{total body}。
(a) \opt{includeheadfoot},(b) \opt{includeall},(c) \opt{includefoot}
及 (d) \opt{includefoot},\opt{includemp}。
如果 \opt{reversemarginpar} 设置为真,则交换 \gpart{marginal note} 与 \gpart{body}
的位置。如果设置了 \opt{twoside},则依据奇偶页交换 \gpart{marginal note}。}
\label{fig:geometry-modes}
\end{figure}
\begin{keyval}[path=layout]{hdivide,vdivide,divide}
\begin{syntax}
hdivide = \{\meta{left margin},\meta{width},\meta{right margin}\}
vdivide = \{\meta{top margin},\meta{height},\meta{bottom margin}\}
divide = \{\meta{length_1},\meta{length_2},\meta{length_3}\}
\end{syntax}
设置两个值,将另一个留空或 \verb|*|。
\end{keyval}
\begin{function}{\bodylmargin,\bodytmargin,\bodyrmargin,\bodybmargin}
\gpart{total body} 的边界距离 \gpart{layout} 边界的左、上、右、下侧的长度。
在 \TikZ 中使用时可能需要用 \tn{the} 获取它们的值,
使用 \cs{dimeval}、\tn{dimexpr} 等命令以及 \pkg{calc} 宏包的功能时则不需要。