-
Notifications
You must be signed in to change notification settings - Fork 0
/
whu-cn.tex
7613 lines (6354 loc) · 312 KB
/
whu-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[twoside]{book}
\PassOptionsToPackage{silent}{xeCJK}
\usepackage{ctex}
\usepackage{fontawesome5}
\makeatletter
\@ifundefined{input@path}{\let\input@path\@empty}{}
\g@addto@macro\input@path{{./module}{./library}{./lt3ekeys}{./whu-doc}{./whu-doc-aux}}
\makeatother
\usepackage[library={doc,box,bnf,ref,counter,pgf}]{whu}
\SetKeys[updatemarks]{multicol}
\newcommand{\hook}{\cmd[module=hook point,type=hook point]}
\newcommand{\colna}{\key[module=color name,type=color name]}
\usepackage{marginnote}
\makeatletter
\newcommand{\sdanger}[1][1]{\par\medskip\noindent\@@line{\hss\Replicate{#1}{\textdbend}\hss}\par}
\newcommand{\mdanger}[1][1]{\marginnote{\Replicate{#1}{\textdbend}}}
\makeatother
\newcommand{\pkgdoc}[1]{\pkg{#1} 宏包文档}
\newcommand*{\TODO}{\textcolor{red!90!black}{\bfseries[TODO]}}
\newcommand\UNEXPANDEDRESULT{最终结果使用 \tn{unexpanded} (\cs{exp_not:n})包裹起来。}
\setuplayout*[balance]{hmargin=1.7cm,top=2.3cm,bottom=2.5cm,
hfoffset=0pt,nomarginpar,
columnsep=35pt,headsep=10pt,footskip=30pt,}
\setuplayout[main]{paper=a4,
marginparsep=10pt,marginparwidth=15\ccwd,
textwidth=35\ccwd,inner=1.7cm,top=2.3cm,bottom=2.5cm,
headsep=10pt,footskip=30pt,
hfoffset={[OR,EL]168.1pt},%marking,%showframe,
}
\usepackage{graphicx}
\setgraphicspath{./whu-doc, ./whu-doc-aux}
\usepackage{xcolor}
%region math & fonts
\usepackage{amsmath,amsfonts}
\usepackage{unicode-math}
% \setmainfont{texgyrepagella}[
% Extension = .otf,
% UprightFont = *-regular,
% BoldFont = *-bold,
% ItalicFont = *-italic,
% BoldItalicFont = *-bolditalic]
\setmainfont{TeXGyreTermesX}[
Extension = .otf,
UprightFont = *-Regular,
BoldFont = *-Bold,
ItalicFont = *-Italic,
BoldItalicFont = *-BoldItalic,
SlantedFont = *-Slanted,
BoldSlantedFont= *-BoldSlanted]
\setsansfont{texgyreheros}[
Extension = .otf,
UprightFont = *-regular,
BoldFont = *-bold,
ItalicFont = *-italic,
BoldItalicFont = *-bolditalic]
\setmonofont{cmun}[
Extension = .otf,
UprightFont = *btl,
BoldFont = *tb,
ItalicFont = *bto,
BoldItalicFont = *tx,
HyphenChar = None]
\setmathfont{texgyrepagella-math.otf}
%endregion
\usepackage{lineno}
\usepackage{caption}
% \expandafter\let\csname caption@ifoddpage\endcsname\IfPageOdd
\usepackage{floatrow}
\usepackage{tikz}
\usetikzlibrary{shadings}
\usepackage[many]{tcolorbox}
\usepackage{listings}
% \usepackage{siunitx}
\usepackage{adjustbox}
\usepackage[strict]{changepage}
\renewcommand{\cplabel}{@}
\usepackage{array,booktabs,tabularx,makecell}
\usepackage{tabularray}
\floatsetup{captionskip=5pt,facing=yes}
\ExplSyntaxOn
\msg_redirect_name:nnn { tabularray } { table-width-too-small } { log }
\ExplSyntaxOff
\usepackage[colorlinks]{hyperref}
\hypersetup{pdfauthor={Longaster, \WhuTeX},
pdftitle=\WhuTeX 宏集手册,
pdfcreator={\XeLaTeX} with hyperref and \WhuLaTeX}
\usepackage{nameref,varioref,cleveref}
\usepackage[numbered,open,openlevel=1]{bookmark}
\usepackage{glossaries}
\usepackage{zhlipsum}
\DeclareNewFloatType{example}{fileext=example,name=例}
\newfloatcommand{mtabbox}{table}[\setcaptiontype{table}\captop][\FBwidth]
\enablecombinedlist
\newsavebox\WaterMarkBox
\sbox{\WaterMarkBox}{\rotatebox{45}{\color{gray!30}\fontsize{100}{0}\sffamily \WhuTeX}}
\background+[./watermark]{\copy\WaterMarkBox}
%region title setting
\makeatletter
\@secpenalty=-\@m
%% 空 mark 实际上保存为了 \prg_do_nothing:,这里并不直接检测,而利用一个空的 mark
\NewMarkClass{totalempty}
\InsertMark{totalempty}{}
\NewMarkClass{chapter/head}
\NewMarkClass{section/head}
\long\def\chaptermark#1{%
\InsertMark{chapter/head}{\protect\hyperlink{\@currentHref}{#1}}%
\InsertMark{section/head}{}}
\long\def\sectionmark#1{%
\InsertMark{section/head}{\protect\hyperlink{\@currentHref}{#1}}}
\def\@chaptosec{\;\texttt{>\kern-.1em >}\;}
\def\@splitrange{\ \texttt{=\kern-.1em =\kern-.2em >}\ }
\def\head@ifempty#1{\ifthenelse{\equal{#1}{}\OR\equal{#1}{\TopMark{totalempty}}}}
\def\head@hifeq#1{\IfMarksEqualTF{#1/head}}
\def\head@ifeq#1#2{\ifthenelse{\equal{#1}{#2}}}
\def\head@ct{\TopMark{chapter/head}} \def\head@st{\TopMark{section/head}}
\def\head@cf{\FirstMark{chapter/head}} \def\head@sf{\FirstMark{section/head}}
\def\head@cl{\LastMark{chapter/head}} \def\head@sl{\LastMark{section/head}}
\def\head@fc#1{{\bfseries #1}} \def\head@fs#1{{#1}}
\newcommand\marked@title{%
\head@hifeq{chapter}{first}{last}{%
\head@ifempty\head@cf{}
{\head@ifempty\head@ct
{\head@fc\head@cf\head@ifempty\head@sl{}{\@chaptosec
\head@ifeq\head@sf\head@sl{\head@fs\head@sf}{\head@fs\head@sf
\head@ifempty\head@sl{}{\@splitrange\head@fs\head@sl}}}}
{\head@ifeq\head@ct\head@cf
{\head@fc\head@ct\head@ifempty\head@sf{}
{\@chaptosec\head@ifeq\head@sf\head@sl
{\head@fs\head@sf}{\head@fs\head@sf\@chaptosec\head@fs\head@sl}}}
{\head@fc\head@ct\head@ifempty\head@st{}{\@chaptosec\head@fs\head@st}\@splitrange
\head@fc\head@cl\head@ifempty\head@sl{}{\@chaptosec\head@fs\head@sl}}}}%
}{\head@fc\head@cf\@splitrange\head@fc\head@cl}}
\setuptitle[chapter]{pagestyle=fancy,
fixskip, break=\needspace{100pt},
beforeskip=30pt, afterskip=25pt, format=\zihao{-2}\bfseries\centering,}
\setuptitle[section]{fixskip, break=\addpenalty{-5000},
name={\texorpdfstring{\S~}{\S}},
beforeskip=20pt plus 5pt minus 5pt, afterskip=15pt plus 2pt minus 2pt,
format=\zihao{-3}\bfseries\raggedright,}
\setuptitle[subsection]{fixskip,
beforeskip=10pt plus 3pt minus 3pt,
afterskip=10pt plus 3pt minus 3pt,
format=\zihao{-4}\bfseries\raggedright,}
\providecommand\headlink@warp[1]{#1}
\setpagestyle{plain}[totalempty]{}
\setpagestyle*{fancy}[totalempty]{
\sethead [ol,er] {\WhuTeX 宏集手册}
\sethead [or,el] {\headlink@warp\marked@title}
% \setfoot [or,el] {\texttt{Longaster@163.com}}
\setfoot [ol,er] {第\thepage 页}
\setheadrulewidth {1pt}
}
\makeatother
%endregion
\makeatletter
\protected\def\this@doc@externallink{\raisebox{-.8ex}[0pt][0pt]{\hi{\faIcon{external-link-alt}}}}
\protected\def\this@doc@linkpage{\raisebox{.8ex}[0pt][0pt]{\lo{P.\labelinfo{page}{\whu@doc@thelabel}}}}
\protected\def\this@doc@linkinfo{\lohi{\,\rmfamily\this@doc@linkpage}{\,\this@doc@externallink}}
\def\whu@doc@basic@format{\ifx\whu@doc@thelabel\@empty \whu@doc@thetext
\else \hyperref[\whu@doc@thelabel]{\whu@doc@thetext\this@doc@linkinfo}\!\fi}
\def\whu@doc@cs@format#1{\hypersetup{linkcolor=whu/color/doc cs}\whu@doc@basic@format}
\let\whu@doc@cmd@format\whu@doc@cs@format
\let\whu@doc@tn@format\whu@doc@cs@format
\def\whu@doc@key@format#1{\hypersetup{linkcolor=whu/color/doc key}\whu@doc@basic@format}
\def\whu@doc@csref@format#1{\whu@doc@basic@format}
\def\whu@doc@envref@format#1{\whu@doc@basic@format}
\def\whu@doc@keyref@format#1{\whu@doc@basic@format}
\setfontface\whu@doc@itfont{texgyrepagella-italic}[Extension=.otf,BoldFont=texgyrepagella-bolditalic]
\makeatother
\definecolor{whu/color/doc cs}{RGB}{180,116,107}
\definecolor{whu/color/doc env}{RGB}{216,156,122}
\definecolor{whu/color/doc key}{RGB}{138,149,169}
\newindextype[auto=true,filename=\jobname.idx,heading*={\section}]{\empty}
\setupindex[\empty,docchange]{auto=false}
%region aux env
\makeatletter
\lstdefinestyle{xamplestyle}{language={[LaTeX]TeX},
basicstyle=\small\linespread{1.1}\ttfamily,
aboveskip=\smallskipamount,belowskip=-\medskipamount,
% aboveskip={0\p@ \@plus 6\p@}, belowskip={0\p@ \@plus 6\p@},
columns=fullflexible, keepspaces=true,
breaklines=true, breakatwhitespace=true,
breakindent=0pt,
postbreak={\hb@xt@1.5em{\hss{\transparent{.3}$\hookrightarrow$}\hss}},
extendedchars=true, nolol,
numberstyle=\tiny,numbersep=8pt,
commentstyle=\color{green!55!black}}
\definebufferpair [ __process_line=standard-not-nest,
save-mode=write, write=\jobname.exambuff, blank=space]
\startxamplecode \stopxamplecode {}
{\edef\xamplecode{\noexpand\lstinputlisting[style=xamplestyle,\unexpanded\expandafter{\xampleOPTlst}]{\jobname.exambuff}}%
\def\xcaption{\setcaptiontype{example}\caption}%
\xample@hango\begin{longfbox}[]\xample@hangi}
\protected\def\xample@hango{%
\par\refstepcounter{example}%
\edef\xample@test{\noexpand\ifnum\the\c@example>\c@example
\global\advance\c@example\@ne\noexpand\fi}}
\protected\def\xample@hangi{%
\setbox\z@\hb@xt@\textwidth{\hss{\color{red!80!black}\bfseries 例\theexample}}%
\global\advance\c@example -\@ne
\vspace*{-\dimexpr\option{/fbox/padding-top}+\parskip}\par
\edef\xample@tmp{\vskip-\the\dimexpr\ht\z@+\dp\z@+.3333em+\parskip\relax\par}%
\box\z@ \xample@tmp}
\protected\def\xampleline{\noindent \kern-\dimexpr\option{/fbox/padding-left}\relax
\cleaders\hb@xt@.2em{\hss.\hss}\hfill
\kern\dimexpr-\option{/fbox/padding-right}\relax \par}
\def\xampletext{\par\input{\jobname.exambuff}}
\def\xampleprint{\xamplecode \xampleline \xampletext}
\NewDocumentEnvironment {xample} { O{} O{} }
{\penalty-1000 \def\xampleOPTlst{#1}%
\fboxset{breakable=true,#2}%
\expandafter\expandafter\expandafter\startxamplecode
\expandafter\string\@firstofone}
{\end{longfbox}\xample@test\goodbreak}
\lstdefinelanguage[BNF]{TeX}[common]{TeX}{
texcs=[1]{BNFItem}, texcs=[2]{BNFN}, texcs=[3]{BNFT},
texcs=[4]{BNFI,is}, texcs=[5]{BNFO,alt},
moredelim=[s][{\color{blue}}]{<}{>},
moredelim=[s][{\color{red!70}}]{"}{"},
literate={{:}{{\bfseries\color{green!50!black}:}}1 {::=}{{\bfseries\color{green!50!black}::=}}3 {|}{{\bfseries\color{cyan}\string|}}1},
texcsstyle={[1]{\color{purple}}}, texcsstyle={[2]{\color{blue}}},
texcsstyle={[3]{\color{red!70}}}, texcsstyle={[4]{\bfseries\color{green!50!black}}},
texcsstyle={[5]{\bfseries\color{cyan}}}}
\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
%endregion
\ExplSyntaxOn
\cs_new:Npn \UseList { \whu_tl_use:nn }
\cs_new:Npn \UseClist { \clist_use:nn }
\ExplSyntaxOff
\crefformat{figure}{#2图#1#3}
\crefformat{table}{#2表#1#3}
\crefformat{example}{#2例#1#3}
\crefformat{part}{#2第\zhnumber{#1}部分#3}
\crefformat{chapter}{#2第\zhnumber{#1}章#3}
\crefformat{section}{第 #2#1#3 节}
\crefformat{subsection}{第 #2#1#3 小节}
\setlist{nosep}
\setlist[itemize,1]{label=\textbullet}
\setlist[itemize,2]{label=$\smwhtcircle$}
\def\nofuncskip{\par\vskip-\bigskipamount\vskip\parskip\par}
\def\zhslash{/}
\raggedbottom \hfuzz=2.5pt \vfuzz=10pt
\title{\WhuTeX 宏集手册}
\author{Longaster}
\date{\zhtoday\quad v\UseName{whu@versi@n}}
\begin{document}
\usepagestyle{totalempty}
\setlength{\lineskiplimit}{4pt}
\setlength{\lineskip}{4pt}
\def\thepage{t.\arabic{page}}
\setuplayout{preset=balance}
\maketitle
\frontmatter
\setpagestyle+{fancy.contents}[fancy]{}
\setuptitle[chapter]{numbering=false,pagestyle=}
\renewcommand{\contentsname}{总目录}
{% \tableofcontents[ragged,outer-sep=0pt,sep=1.5em,2]
\makeatletter
\ekeysdeclarecmd\fixedwidthtext{smm}{\leavevmode@ifvmode
\setbox\z@\hbox{{#3}}%
\ifdim\dimeval{#2}>\wd\z@
\hbox to\dimeval{#2}{%
\IfBooleanTF{#1}{\xeCJKsetup{CJKglue=\hskip 0pt plus 1fill\relax,
CJKecglue=\hskip 0pt plus 1fill\relax}%
\spaceskip 0pt plus 1fill\relax
\CJKglue #3\CJKglue}{#3\hfill}}%
\else
\resizebox{\dimeval{#2}}{\height}{#3}%
\fi}
\definecolor{toccol1}{HTML}{006DAA}
\definecolor{toccol2}{HTML}{C4D4E3}
\newcommand*{\zhphantom}{\vphantom{好hig}}
\tocsetstyle{chapter}{}
{}
{\begingroup\noindent \bfseries\large \fboxrule\z@
\fcolorbox{toccol1}{toccol1}{\zhphantom\color{white}%
\tocifnumbered{\fixedwidthtext*{4\ccwd}{\tocthenumber\unskip}}
{\fixedwidthtext*{4\ccwd}{\tocthename}}}%
\toclinkbox{\fcolorbox{toccol2}{toccol2}{\zhphantom
\fixedwidthtext{\linewidth-4\ccwd-4\fboxsep-1.3em}
{\tocifnumbered{\tocthename}{}}%
\makebox[1.3em][r]{\tocthepage}}}
\endgroup\par \medskip}
{\bigskip}{}
\tocsetstyle{section}{}{}
{\@dottedtocline{\tocthelevel}{1.5em}{2.3em}{\tocthenumber\enskip\tocthename}
{\hss\toclink{\tocthepage}\hspace{\fboxsep}}}
{}{}
\tocsetstyle{subsection}{}{}
{\@dottedtocline{\tocthelevel}{3.8em}{3.2em}{\tocthenumber\enskip\tocthename}
{\hss\toclink{\tocthepage}\hspace{\fboxsep}}}
{}{}
\makeatother
\startmulticolumns[ragged,outer-sep=0pt,column-sep=1.5em,heading=\chapter\contentsname]
\specifiedtoc
\stopmulticolumns
}
\mainmatter
\setuplayout{preset=main}
\usepagestyle{fancy}
\setuptitle[chapter]{numbering=true,pagestyle=fancy}
\removebackground[./watermark]
\chapter{概述}
{\color{red}\bfseries 目前 \WhuTeX 还处于早期的开发状态中,很多功能还并不完善。}
\WhuTeX (\WhuLaTeX)宏集意为 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} 文档类的完整功能不太可能。
如此,本宏集应运而生。
使用 \WhuTeX 可以方便地设置标题、目录、页面样式(页面几何元素、页眉页脚等)、图表、背景、水印、
边注、脚注、列表、索引、术语表等文档元素,具有强大的可定制性。\WhuTeX 原生兼容 \pkg{pgf} 和
\pkg{tcolorbox},加载这两个宏包或使用 \whulibrary{pgf} 库可实现更多的功能 \TODO。
\WhuTeX 通过模块(module)和库(library)来实现诸多功能。其中\emph{模块}是核心部分,
\WhuTeX 将自动加载它们;库是提供额外功能的,用户可以选择是否加载它们。库可能依赖其它模块和库,
但模块不会依赖库。
模块和库均可能加载其它宏包,一般情况下,\WhuTeX 会自动加载这些模块并处理好它们的依赖和兼容性,
当用户需要加载其它宏包时,最好通过 \WhuTeX 的宏包加载机制来加载它们 \TODO。
\WhuTeX 支持 \XeLaTeX、\LuaLaTeX、\upLaTeX、\ApLaTeX(p\LaTeX-ng)等多种编译方式,其中
\LuaLaTeX、\upLaTeX、\ApLaTeX 还支持竖排 \TODO。
\WhuTeX 还很好的支持和适配了通用驱动(generic driver),这是 \LaTeXe 2022-06-01 中的新功能。
\emph{不}兼容 \pkg{beamer}。
\chapter{文档接口}
\WhuTeX 定义的命令有的用于文档中,有的则是面向开发者,本章描述那些在文档中可能使用到的接口。
\begin{function}{\WhuTeX,\WhuLaTeX}
Logo。输出 \WhuTeX,\WhuLaTeX。
\end{function}
\begin{function}{\whusetup}
\begin{syntax}
\verb|\whusetup| \marg{key-vals}
\verb|\whusetup| \oarg{key path} \marg{key-vals}
\verb|\whusetup| \{
~~\meta{key path_1} = \marg{key-vals_1} ,
~~\meta{key path_2} = \marg{key-vals_2} ,
~~...
\}
\end{syntax}
键值设置命令。
\WhuTeX 的不同模块使用不同的 \meta{key path},一般情况下,这些模块会提供自己的键值设置接口,
为了使用 \cs{whusetup} 来设置这些键值,需要指定 \meta{key path}。
\end{function}
在本文档中,键的说明文字旁的表格中列出了键的完整写法,\meta{key path} 即为灰色的部分。
如键 \keyreflist[frame]{outer-sep,sep} 可以写成
\begin{xample}
\whusetup[frame]{outer-sep=0pt, sep=20pt}
或
\whusetup{ frame/outer-sep=0pt, frame/sep=20pt }
\stopxamplecode
\xamplecode\medskip
\end{xample}
\begin{function}{\whusetstyle}
\begin{syntax}
\verb|\whusetstyle| \oarg{key path} \marg{key} \marg{key-vals}
\verb|\whusetstyle| * \oarg{key path} \marg{key} \marg{code}
\end{syntax}
自定义键。
带 \verb|*| 的可使用一个参数,它代表键传入的值。
\end{function}
\section{\whumodule{ltx}模块}
\whumodule{ltx} 模块,本模块封装或提供一些 \LaTeXe 的接口。
\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{material}
\V\makelapbox \oarg{width} \oarg{pos} \marg{material}
\V\makelapbox \oarg{width} \oarg{pos} \oarg{lap to} \marg{material}
\V\parlapbox \marg{width} \marg{material}
\V\parlapbox \oarg{pos} \oarg{height} \oarg{inner-pos} \marg{width} \marg{material}
\V\parlapbox \oarg{pos} \oarg{height} \oarg{inner-pos} \oarg{lap to} \marg{width} \marg{material}
\end{syntax}
\cs{makelapbox} 的用法和 \tn{makebox} 一样,但是会把它向 \meta{lap to} 侧重叠,
\meta{lap to} 默认值和 \oarg{pos} 一样。
\cs{parlapbox} 的用法和 \tn{parbox} 一样,但是会把它向 \meta{lap to} 侧重叠,
\meta{lap to} 默认值为 \texttt{c}。
\end{function}
\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 { 5 } { 12478 }
\ExplSyntaxOff
\stopxamplecode
\xampleprint
\end{xample}
\begin{function}{\zkern}
相当于 \verb|\kern\z@|。
\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}{\whuemoji,\whuemojitotalratio,\whuemojilowerratio}
\begin{syntax}
\V\whuemoji \marg{pic filename}
\end{syntax}
插入一张图片,它的(总)高度为当前文字的高度的 \cs{whuemojitotalratio} 倍,
并向下移动 \cs{whuemojilowerratio} 个文字的高度。
\cs{whuemojitotalratio} 和 \cs{whuemojilowerratio}
必须为 \texttt{0} 或 \veta{a}\texttt/\veta{b},其中 \veta{a}、
\veta{b} 为非零整数。
\cs{whuemojitotal\-ratio} 默认为 \texttt{8/9},如果是负数则上下翻转,但宽度也会变成负值。
\cs{whuemoji\-lowerratio} 默认为 \texttt{1/7},如果是负数则向上移动。
可以用于数学模式,会根据是否处于上下标而改变大小。
需要用户自行加载 \pkg{graphicx} 宏包。
\end{function}
\begin{xample}
\newcommand{\bdhj}{\whuemoji{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}
\V\InputIfGraphicsExists * \oarg{llx,lly} \oarg{urx,ury} \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{\whumodule{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}[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} 钩子中)。
平常使用时并不一定准确,\whumodule{ref} 库改进了这一点,见\cref{sec:lib-ref}。
\end{function}
\begin{function}[EXP]{\@ifpageodd,\@ifabspageodd}
同上,但可展。
\end{function}
\section[float-barrier=on]{页面布局,\whumodule{layout}模块}
\whumodule{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{keyval}[path=layout]{papersize,paperwidth,paperheight}
\begin{syntax}
papersize = \{\meta{宽},\meta{高}\} 或 \{\meta{宽}:\meta{高}\} 或 \marg{长度}
paperwidth = \marg{宽}
paperheight = \marg{高}
\end{syntax}
设置纸张大小。
\end{keyval}
\begin{table}[thb]
\IfPageOdd{\makebox[\linewidth][l]}{\makebox[\linewidth][r]}%
{\includegraphics{tab-defined-papername}}
\caption{预定义的纸张名}\label{tab:defined-papername}
\end{table}
\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} 部分置于纸张中心。