-
Notifications
You must be signed in to change notification settings - Fork 2
/
xcref.dtx
2938 lines (2856 loc) · 114 KB
/
xcref.dtx
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
% \iffalse meta-comment
% -*- coding: utf-8 -*-
%
% File: xcref.dtx Copyright (C) 2019, 2020 Florent Rougon
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in the file
%
% http://www.latex-project.org/lppl.txt
%
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
% The Current Maintainer of this work is Florent Rougon.
%
% This file is part of "xcref" (The Work in LPPL) and all files from
% this Work must be distributed together.
%
% -----------------------------------------------------------------------
%
%<*driver>
% Loading inputenc here to be sure this comes before csquotes (which is loaded
% by l3doc).
\RequirePackage[utf8]{inputenc}
\documentclass{l3doc}
% The next line is needed so that \GetFileInfo will be able to pick up
% version data
\usepackage{xcref}
\usepackage{xparse}
\usepackage{amsmath}
\usepackage[svgnames]{xcolor}
\hypersetup{colorlinks=true, anchorcolor=Lime, linkcolor=RoyalBlue,
urlcolor=Crimson}
% Let's define a few commands and environments used in the documentation
\ExplSyntaxOn
\makeatletter
% l3doc's \file command currently causes errors (on TL 2019)
\RenewExpandableDocumentCommand \file { m }
{ \texttt{#1} }
\NewDocumentCommand \xcrefPGFOpt { m }
{ \pgfkeyRef{/xcref/#1} }
\NewDocumentCommand \xcrefPGFPath { m } % for PGF “directories”
{ \texttt{/xcref/#1} }
\NewDocumentCommand \xcrefPGFRoot { }
{ \texttt{/xcref} }
\NewDocumentCommand \TikZ { }
{
\group_begin:
\upshape Ti\textit{k}Z
\group_end:
}
\NewDocumentCommand \pkgOpt { m }
{ \texttt{#1} }
% Essentially copied from l3doc's texnote environment
\NewDocumentEnvironment { codersnote } { }
{
\endgraf
\vspace{3mm}
\small\textbf{Coders~note:\space}
\ignorespaces
}
{
\vspace{3mm}
}
% ****************************************************************************
% * The 'pgfkey' environment *
% ****************************************************************************
\definecolor { xcrefdoc-keyname-in-def } { HTML } { 9400d3 }
\definecolor { xcrefdoc-keyname-in-ref } { HTML } { 48467c }
\colorlet { xcrefdoc-keyvalue } { black }
% Wrap a few TeX primitives we need
\cs_new_protected:Npn \__xcrefdoc_penalty:n #1
{
\tex_penalty:D #1 \scan_stop:
}
\cs_new_protected:Npn \__xcrefdoc_nobreak:
{
\__xcrefdoc_penalty:n { 10000 }
}
\cs_new_protected:Npn \__xcrefdoc_set_interlinepenalty:n #1
{
\tex_interlinepenalty:D = #1 \scan_stop:
}
\cs_new_protected:Npn \__xcrefdoc_set_endlinechar:n #1
{
\tex_endlinechar:D = #1 \scan_stop:
}
\cs_new_protected:Npn \__xcrefdoc_append_to_everypar:n #1
{
\tex_everypar:D = \exp_after:wN
{
\__xcrefdoc_the:w \tex_everypar:D
#1
}
}
\cs_set_eq:NN \__xcrefdoc_par: \tex_par:D
\cs_set_eq:NN \__xcrefdoc_parfillskip_skip \tex_parfillskip:D
\cs_set_eq:NN \__xcrefdoc_parindent_dim \tex_parindent:D
\cs_set_eq:NN \__xcrefdoc_ignorespaces: \tex_ignorespaces:D
\cs_set_eq:NN \__xcrefdoc_scantokens:n \tex_scantokens:D
\cs_set_eq:NN \__xcrefdoc_the:w \tex_the:D
\cs_set_eq:NN \__xcrefdoc_unpenalty: \tex_unpenalty:D
% Options for use in the second argument of the 'pgfkey' environment
\keys_define:nn { xcrefdoc/pgfkey }
{
annotation~format .code:n =
{
\cs_set:Npn \__xcrefdoc_pgfkey_format_annotation:n ##1 {#1}
},
annotation~format .value_required:n = true,
}
% How to format the annotation for a key. What we call “annotation” here is
% a phrase such as “no default, initially empty”.
\cs_new_protected:Npn \__xcrefdoc_pgfkey_format_annotation:n #1
{ ( {#1} ) }
% This 'pgfkey' environment supports a syntax similar to the tcolorbox
% 'docKey' environment (from the tcolorbox 'documentation' library), however
% the options handled in the third argument of \xcrefdoc_pgfkey_start:Nnnnnnn
% are completely different, and so is the implementation. The star form means
% “don't add this key to the index”. See \xcrefdoc_pgfkey_start:Nnnnnnn for a
% description of the arguments.
\NewDocumentEnvironment { pgfkey } { }
{
% We want to be able to use | to describe alternatives in the arguments of
% \xcrefdoc_pgfkey_start_env, which *appear* as the arguments of this
% environment.
\DeleteShortVerb \"
\DeleteShortVerb \|
\xcrefdoc_pgfkey_start_env
}
{ \xcrefdoc_pgfkey_end: }
\NewDocumentEnvironment { pgfkey* } { }
{
\DeleteShortVerb \"
\DeleteShortVerb \|
\xcrefdoc_pgfkey_start_env *
}
{ \xcrefdoc_pgfkey_end: }
\NewDocumentCommand \xcrefdoc_pgfkey_start_env { s O{} O{} O{} m m +m }
{
\xcrefdoc_pgfkey_start:Nnnnnnn #1 {#2} {#3} {#5} {#6} {#7} {#4}
}
% #1: anchor name
% #2: text
\cs_new_protected:Npn \__xcrefdoc_hypertarget:nn #1#2
{
\hypertarget {#1} {#2}
}
% #1: anchor name
% #2: text
\cs_new_protected:Npn \__xcrefdoc_hyperlink:nn #1#2
{
\hyperlink {#1} {#2}
}
\cs_generate_variant:Nn \__xcrefdoc_hypertarget:nn { x }
\cs_generate_variant:Nn \__xcrefdoc_hyperlink:nn { x }
% Start a \list item; print a key name/path and the value syntax, if any
% #1: key name or path
% #2: key value
% #3: disambigution string (only useful if #1 is not a full path)
\cs_new_protected:Npn \xcrefdoc_pgfkey_start_item:nnn #1#2#3
{
\item []
% Remove the \penalty 0 added (via \everypar) by \@item after \box\@labels
\__xcrefdoc_append_to_everypar:n { \__xcrefdoc_unpenalty: }
\group_begin: % group ended in \xcrefdoc_pgfkey_start:Nnnnnnn
\mode_leave_vertical:
\__xcrefdoc_set_interlinepenalty:n { 10000 }
\skip_zero:N \__xcrefdoc_parfillskip_skip
\raisebox { 0.9\baselineskip } [ 0pt ] [ 0pt ]
{
\__xcrefdoc_hypertarget:xn { \tl_to_str:n { xcrefdoc@pgfkey@#1@#3 } }
{ }
}
\xcrefdoc_pgfkey_format_key:n {#1}
\xcrefdoc_pgfkey_format_value:n {#2}
}
\cs_new_protected:Npn \__xcrefdoc_pgfkey_verb_like:n #1
{
\cs_set_eq:Nc \do { @makeother }
\dospecials
% Make spaces behave normally, not like the “visible space”
\char_set_catcode_space:n { `~ }
\use:c { @noligs }
% Neutralize the final end-of-line of the pseudo-file internally read by
% \scantokens (of course, we assume that #1 consists of only one line).
\__xcrefdoc_set_endlinechar:n { -1 }
\__xcrefdoc_scantokens:n {#1}
}
\cs_new_protected:Npn \xcrefdoc_pgfkey_format_key:n #1
{
\textcolor { xcrefdoc-keyname-in-def }
{
\ttfamily \bfseries
\__xcrefdoc_pgfkey_verb_like:n {#1}
}
}
\cs_new_protected:Npn \xcrefdoc_pgfkey_format_value:n #1
{
\textcolor { xcrefdoc-keyvalue } { \ttfamily #1 }
}
\cs_generate_variant:Nn \xcrefdoc_pgfkey_start_item:nnn { V }
% Assembled key path
\str_new:N \l__xcrefdoc_pgfkey_start_key_str
% Start macro for the 'pgfkey' environment.
%
% The technique used for the paragraph containing the key name/path, value and
% annotation is inspired by the \signed macro described in the TeXbook p. 106.
%
% #1: boolean variable (\c_true_bool or \c_false_bool). True means “don't
% index” and corresponds to the star form of the 'pgfkey' environment.
% #2: key base path (a slash is automatically prepended if this is non-empty)
% #3: options (only 'annotation format' is supported for now)
% #4: key leaf name, relative to the base path
% #5: =\marg{value} or something like that (printed right after the key name)
% #6: annotation for the key (printed flush right to the margin)
% #7: disambiguation string used in the anchor name. This is useful in case the
% key is not given by full path and might have the same name as another key.
\cs_new_protected:Npn \xcrefdoc_pgfkey_start:Nnnnnnn #1#2#3#4#5#6#7
{
\group_begin:
\keys_set:nn { xcrefdoc/pgfkey } {#3}
\list { }
{
\dim_set:Nn { \leftmargin } { 2.5em } % or leave this to the class?
\dim_zero:N \rightmargin
\dim_zero:N \labelwidth
\dim_zero:N \labelsep
\dim_set:Nn { \itemindent } { -\leftmargin }
\dim_zero:N \listparindent
}
\str_set:Nx \l__xcrefdoc_pgfkey_start_key_str
{
\tl_if_blank:nTF {#2}
{ \tl_to_str:n {#4} }
{ \tl_to_str:n {/#2/#4} }
}
% Print the key and value syntax, if any
\xcrefdoc_pgfkey_start_item:Vnn \l__xcrefdoc_pgfkey_start_key_str {#5} {#7}
\bool_if:NF #1 { \xcrefdoc_pgfkey_add_to_index: }
\__xcrefdoc_nobreak:
\skip_horizontal:n { 0pt plus 1fil }
% We prefer having the annotation on the same line as the key, but if the
% key is extremely long, the annotation may be postponed to the next line.
\__xcrefdoc_penalty:n { 50 }
% Ensure some minimal horizontal space between the key and its annotation.
\skip_horizontal:n { 2em }
\hbox:n {} % make sure the following \penalty and glue won't be discarded
\__xcrefdoc_nobreak:
\skip_horizontal:n { 0pt plus 1fil }
\__xcrefdoc_pgfkey_format_annotation:n {#6}
\__xcrefdoc_par:
% End the group started in \xcrefdoc_pgfkey_start_item:n. This restores
% \interlinepenalty and \parfillskip.
\group_end:
\__xcrefdoc_nobreak:
\skip_vertical:n { 0.5ex plus .05ex }
% This can be used to make sure the key description starts with no
% paragraph indentation, in case one has chosen a non-zero \listparindent.
% \group_begin:
% \dim_zero:N \__xcrefdoc_parindent_dim
% \mode_leave_vertical:
% \group_end:
% Reinstate the shortverb chars we disabled when starting the environment
\MakeShortVerb \"
\MakeShortVerb \|
\__xcrefdoc_ignorespaces:
}
\cs_new_protected:Npn \xcrefdoc_pgfkey_end:
{
\endlist
\group_end:
}
\prg_generate_conditional_variant:Nnn \tl_if_head_eq_meaning:nN { V } { T }
\cs_generate_variant:Nn \__codedoc_special_index_set:Nn { NV }
\str_new:N \l__xcrefdoc_pati_escaped_for_sorting_str
\tl_new:N \l__xcrefdoc_pati_escaped_for_typesetting_tl
% XXX We use two private macros of l3doc here (those named \__codedoc_*). This
% has been tested with l3doc released on 2019-10-24.
\cs_new_protected:Npn \xcrefdoc_pgfkey_add_to_index:
{
\str_set_eq:NN \l__xcrefdoc_pati_escaped_for_sorting_str
\l__xcrefdoc_pgfkey_start_key_str
% Escape special characters in the sort key used for indexing purposes
\__codedoc_quote_special_char:N \l__xcrefdoc_pati_escaped_for_sorting_str
% We'll do the same for the token list used for typesetting the entry, but
% let's first replace space tokens by control spaces. As a consequence,
% “visible spaces” won't be used for the PGF key in the index and long
% keys may be broken across lines.
\tl_set_eq:NN \l__xcrefdoc_pati_escaped_for_typesetting_tl
\l__xcrefdoc_pgfkey_start_key_str
\tl_replace_all:Nnn \l__xcrefdoc_pati_escaped_for_typesetting_tl { ~ }
{ \use:c { ~ } }
% Now escape the special characters
\__codedoc_special_index_set:NV \l__xcrefdoc_pati_escaped_for_typesetting_tl
\l__xcrefdoc_pati_escaped_for_typesetting_tl
% Drop a 'hypdoc' anchor (hyperlink target)
\use:c { HD@target }
% Add an index entry that contains a hyperlink pointing to the anchor.
% This entry is sorted under the letter P, as stipulated by the first
% argument. The PGF key is added as a sub-entry of the top-level entry
% “PGF keys”.
\xcrefdoc_add_to_index_aux:n
{
% Sort key for the top-level entry
PGF~keys
\actualchar
% Markup for the top-level entry. Get a ':' with catcode 12 to be
% super clean (it would still work without the call to \tl_to_str:n).
PGF~keys \tl_to_str:n { : }
\levelchar
}
% Prepare to add a second index entry for the same PGF key
\str_set_eq:NN \l__xcrefdoc_pati_escaped_for_sorting_str
\l__xcrefdoc_pgfkey_start_key_str
% If the first token of \l__xcrefdoc_pati_escaped_for_sorting_str is a
% slash character, remove it.
\tl_if_head_eq_meaning:VNT \l__xcrefdoc_pati_escaped_for_sorting_str /
{
\str_set:Nx \l__xcrefdoc_pati_escaped_for_sorting_str
{ \str_tail:N \l__xcrefdoc_pati_escaped_for_sorting_str }
}
\__codedoc_quote_special_char:N \l__xcrefdoc_pati_escaped_for_sorting_str
% Add an index entry sorted according to the “PGF key with its leading
% slash removed” (e.g., sorted as xcref/capitalize if the PGF key is
% /xcref/capitalize). There is no sub-entry this time.
\xcrefdoc_add_to_index_aux:n { }
}
% Add an index entry for a PGF key (\l__xcrefdoc_pati_escaped_for_sorting_str
% and \l__xcrefdoc_pati_escaped_for_typesetting_tl are used). The argument of
% \index, and thus also the argument of \xcrefdoc_add_to_index_aux:n, are
% subject to recursive expansion as in \protected@write \@indexfile {} {...}
% (this is done by \@wrindex).
%
% #1: tokens inserted at the beginning of the argument of \index
\cs_new_protected:Npn \xcrefdoc_add_to_index_aux:n #1
{
\index
{
#1
\l__xcrefdoc_pati_escaped_for_sorting_str % sort key
\actualchar
{ % LaTeX markup
\token_to_str:N \verbatim@font \c_space_tl
\l__xcrefdoc_pati_escaped_for_typesetting_tl
}
\encapchar
% Produce the page number in 'main' style (underlined), with hyperlink.
hdclindex { \__xcrefdoc_the:w \use:c { c@HD@hypercount } } { main }
}
}
% How to format references to PGF keys produced by \xcrefdoc_pgfkeyref:nn
%
% #1: key name or path
\cs_new_protected:Npn \xcrefdoc_format_pgfkeyref:n #1
{
\group_begin:
\ttfamily \__xcrefdoc_pgfkey_verb_like:n {#1}
\group_end:
}
% Write a hyperref-based reference (link) to key #2. #1 is a disambiguation
% string for the anchor name.
\cs_new_protected:Npn \xcrefdoc_pgfkeyref:nn #1#2
{
\group_begin:
\hypersetup { linkcolor = xcrefdoc-keyname-in-ref }
\__xcrefdoc_hyperlink:xn { \tl_to_str:n { xcrefdoc@pgfkey@#2@#1 } }
{ \xcrefdoc_format_pgfkeyref:n {#2} }
\group_end:
}
% Reference a PGF key defined somewhere with the 'pgfkey' environment or its
% starred form. Since the full path to a key should be enough to identify it,
% specifying a non-empty optional argument should only be useful for keys that
% have been presented without the full path (which is probably a bad idea,
% except maybe with deep hierarchies in the pgfkeys namespace...).
%
% #1: disambiguation string for the anchor name
% #2: key name or path
\NewDocumentCommand \pgfkeyRef { O{} m }
{
\xcrefdoc_pgfkeyref:nn {#1} {#2}
}
% End of the code for the 'pgfkey' environment and related commands
\makeatother
\ExplSyntaxOff
\DoNotIndex{\ , \bool_gset_false:N, \bool_gset_true:N, \bool_set_false:N,
\bool_set_true:N, \bool_lazy_and:nnT, \bool_new:N, \bool_if:NTF,
\char_set_catcode_space:n, \clist_map_inline:nn, \cs:w, \cs_end:,
\cs_generate_variant:Nn, \cs_new_protected:Npn, \cs_set:Npn,
\cs_set_eq:NN, \if_meaning:w, \else:, \fi:, \documentclass, \exp_after:wN,
\exp_args:No, \exp_not:N, \exp_not:n, \ExplSyntaxOn, \ExplSyntaxOff,
\forestset, \pgfplotsset, \tikzset, \group_begin:, \group_end:, \input,
\int_new:N, \int_set:Nn, \l_keys_key_tl, \makeatletter, \makeatother,
\msg_error:nn, \msg_error:nnn, \msg_error:nnV, \msg_info:nnn, \msg_new:nnn,
\NeedsTeXFormat, \NewDocumentCommand, \pgfkeys, \pgfqkeys, \keys_define:nn,
\prg_new_conditional:Npnn, \prg_return_false:, \prg_return_true:,
\ProcessKeysOptions, \prop_const_from_keyval:Nn, \prop_get:NnNTF,
\prop_get:NnNF, \prop_get:NVNT, \prop_get:NVNF, \prop_gput:Nnn,
\prop_set_from_keyval:Nn, \prop_gset_from_keyval:Nn, \prop_map_inline:Nn,
\prop_new:N, \ProvidesExplPackage, \relax, \RequirePackage, \robustify,
\seq_clear:N, \seq_gclear:N, \seq_gput_right:Nn, \seq_gput_right:Nx,
\seq_gput_right:NV, \seq_if_in:NnTF, \seq_if_in:NVF, \seq_item:Nn,
\seq_map_function:NN, \seq_map_inline:Nn, \seq_new:N, \seq_pop_left:NN,
\seq_put_right:Nn, \seq_put_right:Nx, \seq_put_right:NV,
\seq_set_split:Nnn, \seq_set_split:NnV, \l_tmpa_seq, \space,
\c_colon_str, \str_case:nnTF, \str_case:nnF, \str_case:VnF,
\str_if_empty:NTF, \str_if_empty:NT, \str_if_eq:nnTF, \str_if_eq:VnT,
\str_new:N, \str_set:Nn, \str_set:Nx, \@firstofone, \@ifpackageloaded,
\@onlypreamble, \protected@xdef, \xcref@tmpa, \tl_clear:N,
\tl_if_empty:NTF, \tl_if_empty:NF, \tl_new:N, \tl_put_left:Nn,
\tl_put_left:NV, \tl_put_right:Nn, \tl_put_right:NV, \tl_replace_all:Nnn,
\tl_set:Nn, \tl_set:No, \tl_set:Nx, \tl_set_eq:NN, \tl_to_str:n,
\l_tmpa_tl, \token_to_str:N, \use:c, \use:n}
\begin{document}
\DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
% \GetFileInfo{xcref.sty}
%
% \title{^^A
% \pkg{xcref} -- Extension of \pkg{cleveref} for non-English languages^^A
% \thanks{This file describes \pkg{xcref}~\fileversion, last revised
% \filedate.}^^A
% }
%
% \author{^^A
% Florent Rougon^^A
% \thanks{^^A
% E-mail: \href{mailto:[email protected]}{mailto:[email protected]}^^A
% }^^A
% }
%
% \date{Released \filedate}
%
% \maketitle
%
% \begin{abstract}
% In non-English languages, words such as prepositions and articles need to
% be adapted in function of the noun they are used with, as well as possibly
% in function of \enquote{cases} such as nominative, accusative, dative, and
% genitive as used in German. As far as I know, these are things that
% \pkg{cleveref} does not allow to do in any practical way, short of
% programming it. This package works on top of \pkg{cleveref} and, given
% language-specific knowledge as well as additional user input (at least to
% select a preposition), it makes it possible to produce references that
% cope with the various forms of ancillary words such as articles and
% prepositions, and don't break when the underlying noun is changed (for
% instance, from chapter to section or theorem to proposition).
% \end{abstract}
%
% \tableofcontents
%
% \begin{documentation}
% \vspace{6ex}
% WARNING: this is an alpha release. Some interfaces may change if they prove
% to be suboptimal. The documentation isn't finished. The code has received
% reasonable testing but might still have bugs.
%
% \section{Introduction}
%
% Generating cross-references to chapters, sections, theorems, lemmas, etc. in
% English is easy, because it can be done in a very simple and mechanical way
% (\enquote{see chapter~1}, \enquote{as we saw in section~2}, \enquote{an
% important consequence of theorems~3 and~4}, etc.). However, it can be more
% difficult in other languages, especially when you expect that the types of
% your references may change: a section might become a chapter after some
% reorganization of your work; a theorem could be downgraded to a proposition,
% etc.
%
% The \pkg{cleveref} package makes it easy to change reference types and have
% the names adapted, however its approach is too simple to work well with
% languages such as French and German. For instance, in French, \enquote{la
% section} would have to become \enquote{le chapitre}, but you can't just use
% \cs{crefname} to tell \cs{cref} to use |la section|, |le chapitre|, etc. as
% the \emph{names} associated to the |section| and |chapter| reference types,
% because depending on the preposition that is used, you need various forms:
% \enquote{\`a la section}, \enquote{au chapitre}, \enquote{de la section},
% \enquote{du chapitre}, \enquote{d'apr\`es la section}, \enquote{d'apr\`es le
% chapitre}, etc. Exactly the same happens with \enquote{th\'eor\`eme} and
% \enquote{proposition} (these are French words). Fortunately, there is enough
% regularity in how these various forms are produced to allow writing code
% that automatically produces correct French with input such as
% |\xcref[french/preposition=d'après]{some-label}|.
%
% Note that convenience wrappers are provided to shorten the previous command
% (see section~\ref{sec:language-specific-convenience-wrappers} and the
% example files) and that several labels can be used in the same command, when
% one wishes \pkg{cleveref} to combine them; this works especially well when
% all such labels are of the same type.
%
% Other languages have rules of the same kind and can also be nicely
% accomodated. For instance, with the |ngerman| module, one can reference two
% propositions with the \enquote{nach} preposition using code such as:
% \begin{verbatim}
% \xcref[ngerman/preposition=nach]{some-prop,other-prop}
% \end{verbatim}
% (again, there are convenience wrappers to make this shorter).
% \pkg{xcref} knows that \enquote{nach} is always followed by the dative case,
% so it will produce reference text such as \enquote{nach den Propositionen
% 3~und~4}. With the \xcrefPGFOpt{ngerman/form} option (which has its
% counterpart in the \texttt{french} module), one can obtain variant forms: in
% the same conditions,
% \begin{verbatim}
% \xcref[ngerman/form=article+noun]{some-prop,other-prop}
% \end{verbatim}
% would yield \enquote{den Propositionen 3~und~4} and
% \begin{verbatim}
% \xcref[ngerman/form=noun]{some-prop,other-prop}
% \end{verbatim}
% would produce \enquote{Propositionen 3~und~4} (exactly the same options are
% available in the \texttt{french} module along with the initial value
% |prep+article+noun|, however this may not fit all languages, hence the use
% of the \xcrefPGFPath{ngerman} and \xcrefPGFPath{french} namespaces for the
% |form| option). In German, it is
% also possible, and very often necessary, to indicate which case to use
% among nominative, accusative, dative and genitive, since in many cases,
% understanding the sentence is required to choose the appropriate case. This
% can be done using the \xcrefPGFOpt{ngerman/case} option which can take the
% values |nom|, |acc|, |dat|, and |gen|.
%
% \section{Installation}
%
% \subsection{Code}
%
% Installation of \pkg{xcref} can be done with the following steps:
% \begin{enumerate}
% \item Go to the directory containing |build.lua| and |xcref.dtx|.
% \item
% \begin{enumerate}
% \item If you have |l3build| and agree to install \pkg{xcref} in the
% appropriate place under |TEXMFHOME|, run the command |l3build install|.
%
% If you want to use a different base directory, you can pass the
% |--texmfhome| option (e.g., |--texmfhome=|\meta{your~choice}) after
% |l3build install|. In order to see which files would be installed
% without actually installing them, run |l3build install --dry-run|. See
% |texdoc l3build| for more details.
% \item Otherwise, run |tex xcref.ins| (or |pdftex xcref.ins|, etc.) in
% order to extract |xcref.sty| and the |xcref-*.tex| language modules from
% |xcref.dtx| to the current directory (unless you have a |docstrip.cfg|
% file that says otherwise, of course). Then, install the extracted files
% as usual in a place listed in your |TEXINPUTS| and refresh the
% \enquote{filename database} of your \TeX{} distribution if needed.
% \end{enumerate}
% \end{enumerate}
%
% Once these steps have been performed, you should be able to build this
% document yourself (see below) and compile the \texttt{*.tex} files in the
% \texttt{examples} directory.
%
% \subsection{Documentation}
%
% In order to build the documentation (\texttt{xcref.pdf}), you need to have
% |xcref.sty| somewhere in your |TEXINPUTS|. How to do so is explained in the
% previous section. We'll assume you've already done that. There are
% essentially two ways to build he documentation. In either case, the first
% thing to do is to go to the directory containing |build.lua| and
% |xcref.dtx|.
%
% \subsubsection*{With \texttt{l3build}}
%
% This is the easiest way: simply run |l3build doc|.
%
% \subsubsection*{Without \texttt{l3build}}
%
% Run a \LaTeX-based engine on |xcref.dtx|. You also need to use |makeindex|
% to generate the index. For instance, the following command sequence is
% likely to produce a correct \pkg{xcref} manual:
% \begin{verbatim}
% pdflatex xcref.dtx
% makeindex -s gind.ist -o xcref.ind xcref.idx
% pdflatex xcref.dtx
% pdflatex xcref.dtx
% makeindex -s gind.ist -o xcref.ind xcref.idx
% pdflatex xcref.dtx
% \end{verbatim}
%
% \subsubsection*{Choosing a different paper size}
%
% Note: the following won't work unless your |l3doc.cls| is from 2019-09-18 or
% later (see
% \href{https://github.com/latex3/latex3/commit/ef39a40f586f8bec2464b4610e0d99c0f6411b6d}{\LaTeX3 commit ef39a40f586f}).
%
% \medskip
% In case you want the documentation to be produced in A4 format, create a
% file named |l3doc.cfg| in the directory containing |xcref.dtx|, with the
% following contents:
% \begin{verbatim}
% \PassOptionsToClass{a4paper}{l3doc}
% \end{verbatim}
% then run |l3build doc| as usual.
%
% \subsubsection*{Removing generated files}
%
% You can remove generated files (not only from the documentation build) with
% the |l3build clean| command. Note: this will remove |xcref.pdf| too.
%
% \section{Usage}
%
% \subsection{Package options}
% \label{sec:package-options}
%
% The \pkg{xcref} package accepts only one fixed option, namely
% \pkgOpt{languages}. The other options are names of language modules, such as
% |french| and |ngerman|. The \pkgOpt{languages} option accepts a
% comma-separated list of languages, therefore the following are equivalent:
% \begin{itemize}
% \item
% \begin{verbatim}
% \usepackage[french, ngerman]{xcref}
% \end{verbatim}
% \item
% \begin{verbatim}
% \usepackage[languages={french, ngerman}]{xcref}
% \end{verbatim}
% \item
% \begin{verbatim}
% \usepackage{xcref}
% \xcrefusemodules{french, ngerman}
% \end{verbatim}
% \end{itemize}
%
% Language modules are loaded in the specified order in each of these three
% examples, but no module is loaded twice. Therefore,
% \begin{verbatim}
% \usepackage[ngerman,french,ngerman]{xcref}
% \end{verbatim}
% will load the \texttt{ngerman} module followed by the \texttt{french} module
% and stop there.
%
% Unless you intend to write \pkg{xcref}-managed cross-references in several
% languages, you only need to load one language module, and its name can very
% well be picked from the \tn[no-index]{documentclass} options. The language
% in which cross-references are written in the document is not determined by
% the load order of language modules, but by the current \pkg{babel} language
% at that point in the document or by the \xcrefPGFOpt{lang} PGF key if
% specified (which then takes precedence over the current \pkg{babel}
% language).
%
% \subsection{PGF keys}
%
% The options defined in this section are managed by \pkg{pgfkeys}. In what
% follows, they will be referred to as \emph{PGF keys}, or simply \emph{keys}.
% These options can be used in:
% \begin{itemize}
% \item the optional argument of \cs{xcref} (first argument of \cs{xcref:nn});
% \item the argument of \cs{xcrefset} (and thus of \cs{xcref_set:n}).
% \end{itemize}
%
% \subsubsection{Generic}
%
% \begin{pgfkey}[xcref]{capitalize}{=true|false}{default \texttt{true},
% initially \texttt{false}}
% When set to |true|, causes references to start with a capital letter.
% Capitalization can be inhibited for specific parts of a reference text
% by means of macros listed via \pgfkeyRef{/xcref/functions for preventing
% auto case change}.
% \end{pgfkey}
%
% \begin{pgfkey}[xcref]{hyperlinks}{=true|false}{default \texttt{true},
% initially \texttt{true}}
% When \pkg{hyperref} is loaded, the value |true| causes \pkg{xcref} to use
% hyperlinks in references.
% \end{pgfkey}
%
% \begin{pgfkey}[xcref]{lang}{=\meta{language}}{no default, initially empty}
% Determine the language in which references are to be typeset. This doesn't
% cause \pkg{xcref} to change the current \pkg{babel} or \pkg{polyglossia}
% language---this aspect is entirely up to you. \meta{language} should be
% either empty or the name of an \pkg{xcref} language module, such as
% |french| or |ngerman| (so far, these are \pkg{babel} language names and
% this will remain so unless there is a good reason to depart from this
% naming scheme). If \meta{language} is empty, the language to use is
% autodetected whenever \pkg{xcref} is asked to typeset a reference. This is
% done with the \pkg{iflang} package and uses the language that is current
% at the point where the reference is typeset.
%
% Except for the empty value, only languages corresponding to an existing
% \pkg{xcref} language module can be used as \meta{language}. Language
% modules are stored in files named \texttt{xcref-\meta{language}.tex} next
% to \file{xcref.sty} in
% |$TEXMF/tex/latex/xcref|. Their source code can be found by looking for
% markers such as |%<*french-module>| and |%<*ngerman-module>| in
% \file{xcref.dtx}. When \pkg{xcref} is loaded, the \texttt{seq} variable
% \cs{g_xcref_available_language_modules_seq} contains all available
% language modules, and \cs{g_xcref_loaded_language_modules_seq} contains
% all those that have been loaded so far (see \pkg{l3seq} in
% \href{http://mirrors.ctan.org/macros/latex/contrib/l3kernel/interface3.pdf}{\file{interface3.pdf}}).
% \end{pgfkey}
%
% \begin{pgfkey}[xcref]{functions for preventing auto case change}
% {=\meta{macros}}{no default, initially \cs{xcrefNoCaseChange}}
% List of macros that prevent automatic case change on particular pieces of
% text when references are capitalized (see~\pgfkeyRef{/xcref/capitalize}).
% \meta{macros} should be one or more control sequence tokens. Each of these
% tokens should be the name of a macro that accepts one argument. When
% \cs{text_titlecase:nn} is called to capitalize a reference, each such macro
% present in the reference text protects its argument from changes by
% \cs{text_titlecase:nn}.
%
% Note that \cs{text_titlecase:nn} doesn't expand the macros listed in
% \meta{macros}; it only uses them to detect which parts of a reference text
% mustn't be modified. The macro calls will be left as is in the reference
% text; thus, a reasonable behavior for a macro listed in \meta{macros} is
% to simply expand to its only argument. This is precisely what
% \cs{xcrefNoCaseChange} does, which is defined to behave exactly like
% \cs{use:n}. That said, you are free to define and use macros that do
% something else with their argument: you might want them to typeset it in a
% special font, use a particular color, etc.
% \end{pgfkey}
%
% \begin{pgfkey}[xcref]{lang for capitalization func}{=\meta{macro}}
% {no default, initially \cs{xcrefDefaultMappingForTextTitleCase}}
% Change the function used by \pkg{xcref} to map language module names to
% language codes suitable for use with \cs{text_titlecase:nn}. The function
% in question is called when producing a capitalized reference. See the
% documentation of \cs{xcref_lang_for_text_titlecase:n} for the requirements
% that apply to such a function.
% \end{pgfkey}
%
% \subsubsection{\texttt{french} langage module}
%
% \begin{pgfkey}[xcref/french]{form}{=\meta{form}}
% {no default, initially \texttt{prep+article+noun}}
% Specifies which grammatical form to use for references. The available
% choices are |noun|, |article+noun| and |prep+article+noun|, where |prep|
% stands for \enquote{preposition}.
% \end{pgfkey}
%
% \begin{pgfkey}[xcref/french]{preposition}{=\meta{prep}}
% {no default, initially empty}
% Preposition to use in references. When non-empty, \meta{prep} overrides
% the default preposition associated to the reference type.
% \end{pgfkey}
%
% ^^A The initial value is intentionally not specified. What would be a really
% ^^A good initial value? This seems difficult to answer.
% \begin{pgfkey}[xcref/french]{names table}{=\meta{data}}{no default}
% Define how to write each reference type in French. \meta{data} must be a
% comma-separated list of (key, value) pairs, where each pair has the form
% \texttt{\meta{reftype}=\meta{value}}. Each \meta{reftype} must be a
% reference type and the corresponding \meta{value} should consist in four
% items (see below), the first two of which must be in LICR
% form.\footnote{This implies that in the first two items of each
% \meta{value}, you should use syntax such as \texttt{\textbackslash `e} or
% \texttt{\textbackslash 'e} instead of \texttt{é} or \texttt{è}.} In each
% \meta{value}, the first item is the \emph{default preposition} for
% reference type \meta{reftype}. Here is an example where, for instance, the
% default preposition for reference type |assertion| is defined to be
% |d'apr\`es| (which is typeset as \enquote{d'après}):
% \begin{verbatim}
% \xcrefset{
% french/.cd,
% names table = {
% problem = {\`a}{le}{problème}{problèmes},
% proposition = {\`a}{la}{proposition}{propositions},
% assertion = {d'apr\`es}{l'}{assertion}{assertions},
% theorem = {\`a}{le}{théorème}{théorèmes},
% lemma = {\`a}{le}{lemme}{lemmes},
% definition = {dans}{la}{définition}{définitions},
% }
% }
% \end{verbatim}
% Note: \pkg{xcref} knows that in French,
% $\texttt{\textbackslash `a} + \texttt{le}$ results in
% \enquote{au} in singular form and in \enquote{aux} in plural form, that the
% plural form of definite article |l'| is |les|, etc.
% \end{pgfkey}
%
% ^^A Is the current initial value (not documented here) the definitive one?
% \begin{pgfkey}[xcref/french]{composition table for prepositions and articles}
% {=\meta{data}}{no default}
% Define how a given preposition combines with the definite articles |l'|,
% |le| , |la| and |les|. \meta{data} must be a comma-separated list of (key,
% value) pairs, where each pair has the form
% \texttt{\meta{prep}=\meta{value}}. Each \meta{prep} must be a preposition in
% LICR form (see above) and the corresponding \meta{value} should consist in
% four items. These items respectively indicate how to combine preposition
% \meta{prep} with the definite articles |l'|, |le| , |la| and |les|.
% Example:
% \begin{verbatim}
% \xcrefset{
% french/.cd,
% composition table for prepositions and articles = {
% \`a = {à l'}{au }{à la }{aux },
% de = {de l'}{du }{de la }{des },
% }
% }
% \end{verbatim}
% \end{pgfkey}
%
% \subsubsection{\texttt{ngerman} langage module}
%
% \begin{pgfkey}[xcref/ngerman]{form}{=\meta{form}}
% {no default, initially \texttt{prep+article+noun}}
% Specifies which grammatical form to use for references. The available
% choices are |noun|, |article+noun|, |prep+noun| and |prep+article+noun|,
% where |prep| stands for \enquote{preposition}.
% \end{pgfkey}
%
% \begin{pgfkey}[xcref/ngerman]{preposition}{=\meta{prep}}
% {no default, initially empty}
% Preposition to use in references. When non-empty, \meta{prep} overrides
% the default preposition associated to the reference type.
% \end{pgfkey}
%
% \begin{pgfkey}[xcref/ngerman]{case}{=\meta{case}}
% {no default, no initial value}
% Specify which case to use among nominative, accusative, dative and
% genitive. The corresponding values for \meta{case} are respectively |nom|,
% |acc|, |dat| and |gen|. Since there is no initial value, you must set this
% key one way or another when typesetting references with \pkg{xcref}'s
% \texttt{ngerman} module. An easy way to do that is to decide on a default
% case for some part or all of your document (say, dative) and declare it
% like this (\cs{xcrefset} respects \TeX's grouping rules):
% \begin{verbatim}
% \xcrefset{ngerman/case=dat}
% \end{verbatim}
% \end{pgfkey}
%
% \begin{pgfkey}[xcref/ngerman]{names table}{=\meta{data}}{no default}
% Define how to write each reference type in German. \meta{data} must be a
% comma-separated list of (key, value) pairs, where each pair has the form
% \texttt{\meta{reftype}=\meta{value}}. Each \meta{reftype} must be a
% reference type and the corresponding \meta{value} should consist in five
% items. More precisely, each \meta{value} should be of the form:
% \begin{quote}^^A One could use \Arg, but that wouldn't be really correct...
% |{|\meta{default-prep}|}{|^^A
% \meta{nominative}|}{|^^A
% \meta{accusative}|}{|^^A
% \meta{dative}|}{|^^A
% \meta{genitive}|}|
% \end{quote}
% where \meta{default-prep} defines the default preposition\footnote{In LICR
% form: for instance, \texttt{f\textbackslash \textquotedbl ur}.} for
% reference type \meta{reftype} and each of the \meta{nominative},
% \meta{accusative}, \meta{dative} and \meta{genitive} placeholders should
% be of the form
% |{|\meta{article-sing}|}{|\meta{noun-sing}|}{|\meta{article-plur}|}{|\meta{noun-plur}|}|,
% where the four metasyntactic variables represent the definite article and
% noun to use for reference type \meta{reftype} in singular and plural
% forms, respectively. Like the default preposition \meta{default-prep},
% each of the eight definite articles must be in LICR form. Here
% is an example where, for instance, the default preposition for reference
% type |proposition| is defined to be |nach|:
% \begin{verbatim}
% \xcrefset{
% ngerman/.cd,
% names table = {
% problem = {in}{{das}{Problem}{die}{Probleme}}%
% {{das}{Problem}{die}{Probleme}}%
% {{dem}{Problem}{den}{Problemen}}%
% {{des}{Problems}{der}{Probleme}},
% proposition= {nach}{{die}{Proposition}{die}{Propositionen}}%
% {{die}{Proposition}{die}{Propositionen}}%
% {{der}{Proposition}{den}{Propositionen}}%
% {{der}{Proposition}{der}{Propositionen}},
% satz = {nach}{{der}{Satz}{die}{Sätze}}%
% {{den}{Satz}{die}{Sätze}}%
% {{dem}{Satz}{den}{Sätzen}}%
% {{des}{Satzes}{der}{Sätze}},
% }
% }
% \end{verbatim}
% Note: \pkg{xcref} knows that in German, $\texttt{in} + \texttt{dem}$
% results in \texttt{im}, etc. (if something like this has been forgotten by
% the package author, it just needs to be added to
% \cs{l_xcref_ngerman_article_and_prep_prop}).
%
% There is an \emph{initial} value, but I'm not sure it is a great idea to
% set it in stone now by documenting it here.
% \end{pgfkey}
%
% \begin{pgfkey}[xcref/ngerman]{prepositions always followed by the same case}
% {=\meta{data}}{no default}
% \meta{data} must be a comma-separated list of (key, value) pairs, where
% each pair has the form \texttt{\meta{prep}=\meta{case}}. Each such pair
% declares that preposition \meta{prep} is always followed by \meta{case}
% (this overrides \xcrefPGFOpt{ngerman/case}). Each \meta{prep} must be
% given in LICR form and each \meta{case} must be one of
% \texttt{nominative}, \texttt{accusative}, \texttt{dative} and
% \texttt{genitive}.
%
% There is an \emph{initial} value, but I'm not sure it is a great idea to
% set it in stone now by documenting it here.
% \end{pgfkey}
%
% \begin{pgfkey}[xcref/ngerman]{composition table for prepositions and articles}
% {=\meta{data}}{no default}
% Define how a given preposition combines with the definite article, in the
% cases where simple concatenation with a space doesn't give the correct
% result. For instance, |in dem = im| must be declared here if one wants to
% have this contraction instead of \texttt{in dem}; on the other hand, since
% \texttt{in der} can be obtained by simple concatenation, it doesn't need
% to (and should not) be specified here.
%
% \meta{data} must be a comma-separated list of (key, value) pairs, where
% each pair has the form \texttt{\meta{key}=\meta{value}}. Each \meta{key}
% must be written in LICR form.\footnote{For instance, should you want to
% use the preposition \enquote{für} inside a \meta{key}, it would have to be
% written as \texttt{f\textbackslash \textquotedbl ur}, not \texttt{für}.}
% As an example, the initial value of \xcrefPGFOpt{ngerman/composition table
% for prepositions and articles} at the time of this writing is equivalent
% to the following setting:
% \begin{verbatim}
% \xcrefset{
% ngerman/.cd,
% composition table for prepositions and articles = {
% an dem = am,
% in dem = im,
% von dem = vom,
% zu dem = zum,
% zu der = zur,
% bei dem = beim,
% }
% }
% \end{verbatim}
% While this is currently the initial value, it may be unwise to expect it
% to always remain the same---I wrote this initial setting and am not a
% native German speaker, thus the initial setting might receive improvements
% in the future. If you want to be preserved from future changes, specify
% the desired value yourself in your documents (possibly in a personal style
% file) using an |\xcrefset| call as shown above.
% \end{pgfkey}
%
% \subsection{Generic macros}
%
% \begin{function}{\xcrefusemodules, \xcref_use_modules:n,
% \xcref_use_module:n, \xcref_use_module:V}
% \begin{syntax}
% \cs{xcrefusemodules}|{|\meta{language_1},\ldots,\meta{language_n}|}|
% \cs{xcref_use_modules:n} |{|\meta{language_1},\ldots,\meta{language_n}|}|
% \cs{xcref_use_module:n} \Arg{language}
% \end{syntax}
% Add the specified languages to the list of requested language-specific
% modules. Example values for the language metasyntactic variables are
% \texttt{french} and \texttt{ngerman}. These commands can only be used in
% the preamble.
% \end{function}
%
% \begin{function}{\xcref, \xcref:nn}
% \begin{syntax}
% \cs{xcref}\oarg{options}\marg{comma-separated list of references}
% \cs{xcref:nn} \Arg{options} \Arg{comma-separated list of references}
% \end{syntax}
% \pkg{xcref}'s equivalent of \cs{cref}, \cs{Cref} and starred forms of
% these.
%
% The \meta{options} are processed with \pkg{pgfkeys} with a default path of
% \xcrefPGFRoot. The references are passed as is to \cs{cref} or \cs{Cref},
% depending on the value of \xcrefPGFOpt{capitalize} (a starred form is