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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
|
% ======================================================================
% scrbase.tex
% Copyright (c) Markus Kohm, 2002-2021
%
% This file is part of the LaTeX2e KOMA-Script bundle.
%
% This work may be distributed and/or modified under the conditions of
% the LaTeX Project Public License, version 1.3c of the license.
% The latest version of this license is in
% http://www.latex-project.org/lppl.txt
% and version 1.3c or later is part of all distributions of LaTeX
% version 2005/12/01 or later and of this work.
%
% This work has the LPPL maintenance status "author-maintained".
%
% The Current Maintainer and author of this work is Markus Kohm.
%
% This work consists of all files listed in manifest.txt.
% ----------------------------------------------------------------------
% scrbase.tex
% Copyright (c) Markus Kohm, 2002-2021
%
% Dieses Werk darf nach den Bedingungen der LaTeX Project Public Lizenz,
% Version 1.3c, verteilt und/oder veraendert werden.
% Die neuste Version dieser Lizenz ist
% http://www.latex-project.org/lppl.txt
% und Version 1.3c ist Teil aller Verteilungen von LaTeX
% Version 2005/12/01 oder spaeter und dieses Werks.
%
% Dieses Werk hat den LPPL-Verwaltungs-Status "author-maintained"
% (allein durch den Autor verwaltet).
%
% Der Aktuelle Verwalter und Autor dieses Werkes ist Markus Kohm.
%
% Dieses Werk besteht aus den in manifest.txt aufgefuehrten Dateien.
% ======================================================================
%
% Package scrbase for Package and Class Authors
% Maintained by Markus Kohm
%
% ----------------------------------------------------------------------
%
% Paket scrbase fuer Paket- und Klassenautoren
% Verwaltet von Markus Kohm
%
% ======================================================================
\KOMAProvidesFile{scrbase.tex}
[$Date: 2021-10-16 12:22:12 +0200 (Sat, 16 Oct 2021) $
KOMA-Script package scrbase]
\translator{Markus Kohm\and Melvin Hendrix\and Karl Hagen}
% Date of the translated German file: 2021-10-16
\chapter{Basic Functions in the \Package{scrbase} Package}
\labelbase{scrbase}
\BeginIndexGroup
\BeginIndex{Package}{scrbase}%
The \Package{scrbase} package provides basic features intended for use by
authors of packages and classes. Its use is not limited merely to wrapper
classes which in turn load a \KOMAScript{} class. Authors of classes that
otherwise have nothing to do with \KOMAScript{} can also benefit from the
functionality of \Package{scrbase}.
\section{Loading the Package}
\seclabel{loadit}
Whereas users load packages with \Macro{usepackage}, authors of packages or
classes should use \Macro{RequirePackage}\IndexCmd{RequirePackage}. Authors of
wrapper packages can also use \Macro{RequirePackageWithOptions}. The
\Macro{RequirePackage} command has the same optional argument for package
options as \Macro{usepackage}. In contrast, \Macro{RequirePackageWithOptions}
does not have an optional argument but passes to this package all the options
that were previously given when loading the wrapper package or class. See
\cite{latex:clsguide} for more information about these commands.
The \Package{scrbase} package needs the functionality of the
\Package{keyval}\IndexPackage{keyval} package internally. This can also be
provided by the \Package{xkeyval} package. If needed, \Package{scrbase} itself
loads \Package{keyval}.
The \Package{keyval} package lets you define keys and assign values to them.
The options provided by \Package{scrbase} also use \Package{keyval} syntax:
\PName{key}\texttt{=}\PName{value}.
\section{Keys as Attributes of Families and Their Members}
\seclabel{keyvalue}
As already mentioned in \autoref{sec:scrbase.loadit}, \Package{scrbase} uses
the \Package{keyval} package to set keys and their values. However,
\Package{scrbase} extends this functionality. Whereas with \Package{keyval} a
key belongs to only one family, \Package{scrbase} also recognizes family
members. A key can therefore belong to both a family and one or more family
members. Additionally, you can assign a value to the key of a family member,
to the key of a family, or to the keys of all family members.
\begin{Declaration}
\Macro{DefineFamily}\Parameter{family}%
\Macro{DefineFamilyMember}\OParameter{member}\Parameter{family}%
\end{Declaration}
\Package{scrbase} needs to know the members of a family for various reasons.
Therefore, you must first define a new family using \Macro{DefineFamily},
which produces an empty member list. If the family has already been defined,
nothing happens. Therefore an existing member list will not be overwritten.
Next, you can add a new member to the family using \Macro{DefineFamilyMember}.
If the family does not exist, this will result in an error message. If the
member already exists, nothing happens. If the optional \PName{member} is
omitted, the default value
``\texttt{.}\Macro{@currname}\texttt{.}\Macro{@currext}'' is used. While
the class or package is being loaded, \Macro{@currname} and \Macro{@currext}
together represent the file name of the class or package.
Theoretically, it is possible, to define a member without a name using an
empty optional \PName{member} argument. But this is the same as the family
itself. You should use only letters and digits for the \PName{family} name,
and the first character of \PName{member} should be something else, preferably
a point. Otherwise, it could happen that the members of one family will clash
with the members of other families.
\Package{scrbase} assigns the family ``\PValue{KOMA}'' to itself and adds the
member ``\PValue{.scrbase.sty}''. The values ``\PValue{KOMA}'' and
``\PValue{KOMAarg}'' are reserved for \KOMAScript{}. If you are creating a
bundle of packages, you should use the name of the bundle as \PName{family}
and the name of each package as \PName{member} of that \PName{family}.
%
\begin{Example}
Suppose you are writing a bundle called ``master butcher''. Within that
bundle, you have the packages \File{salami.sty}, \File{mettwurst.sty},
and \File{kielbasa.sty}. Therefore, you decide to use family name
``\PValue{butcher}'' and you add the lines
\begin{lstcode}
\DefineFamily{butcher}
\DefineFamilyMember{butcher}
\end{lstcode}
to each of the package files. When loading the three packages, this will
add the members ``\PValue{.salami.sty}'', ``\PValue{.mettwurst.sty}'',
and ``\PValue{.kielbasa.sty}'' to the family ``\PValue{butcher}''. After
loading all three packages, all three members will be defined.
\end{Example}
%
\EndIndexGroup
\begin{Declaration}
\Macro{DefineFamilyKey}\OParameter{member}\Parameter{family}%
\Parameter{key}%
\OParameter{default}\Parameter{action}%
\Macro{FamilyKeyState}%
\Macro{FamilyKeyStateUnknown}%
\Macro{FamilyKeyStateProcessed}%
\Macro{FamilyKeyStateUnknownValue}%
\Macro{FamilyKeyStateNeedValue}
\end{Declaration}
The \Macro{DefineFamilyKey} command defines a \PName{key}. If you specify a
\PName{member}, the \PName{key} becomes an attribute of that member in the
given \PName{family}. If you do not specify a \PName{member}, the member
``\texttt{.}\Macro{@currname}\texttt{.}\Macro{@currext}'' is assumed. If you
later assign a value to the \PName{key}, the \PName{action} will be
executed and the value made an argument of \PName{action}. Within
\PName{action}, ``\lstinline{#1}'' stands for that value. If you omit the value,
the \PName{default} is used instead. If you do not specify a \PName{default},
the \PName{key} then always requires you to pass an explicit value.
%\begin{Explain}
\phantomsection\label{explain:scrbase.macro.DefineFamilyKey}%
Ultimately,
\begin{lstcode}[escapeinside=`']
\DefineFamilyKey[`\PName{member}']{`\PName{family}'}{`\PName{key}'}
[`\PName{default}']{`\PName{action}'}
\end{lstcode}
results in a call to
\begin{lstcode}[moretexcs={define@key},escapeinside=`']
\define@key{`\PName{family\,member}'}{`\PName{key}'}
[`\PName{default}']{`\PName{extended action}'}
\end{lstcode}
where \Macro{define@key} is provided by the
\Package{keyval}\IndexPackage{keyval} package (see \cite{package:keyval}).
However, there are some additional precautions taken with the call to
\Macro{define@key}, and the \PName{action} will be extended to include these
precautions.
%\end{Explain}
Success\ChangedAt{v3.12}{\Package{scrbase}} or failure in executing the
\PName{action} should be reported back to \Package{scrbase} through
\Macro{FamilyKeyState} so that the package itself can take further action as
needed. This could be, for example, an error message or merely warning of an
unknown option. You should not report errors directly!
The default state of \PName{action} before execution is
\Macro{FamilyKeyStateUnknown}. This indicates that it is not known whether or
not the key could be processed successfully. If this state remains unchanged
after the \PName{action} has been executed, \Package{scrbase} writes a
message to the \File{log} file and assumes the that state is
\Macro{FamilyKeyStateProcessed}.
The \Macro{FamilyKeyStateProcessed} state indicates that the key and the value
assigned to it have been successfully processed and everything is OK. You can
switch to this state by calling \Macro{FamilyKeyStateProcessed} itself.
The \Macro{FamilyKeyStateUnknownValue} state indicates that the key has been
processed but that the value passed to it was either unknown or not allowed.
For example, \hyperref[cha:typearea]{\Package{typearea}} reports this
condition if you try to set the \DescRef{typearea.option.twoside} option to
\PValue{unknown}. You can set this state by simply calling
\Macro{FamilyKeyStateUnknownValue}.
The \Macro{FamilyKeyStateNeedValue} state indicates that the key could not be
processed because it expects a value, but it was called without such a value.
This state is set automatically if you use a key that does not have a
\PName{default} value without assigning a value. Theoretically, you could
set this state explicitly with \Macro{FamilyKeyStateNeedValue}, but you should
not need to set it yourself.
In addition, you can define additional error conditions by redefining
\Macro{FamilyKeyState} with a short text message. Generally, however, the four
predefined states should be sufficient.
\begin{Example}
Suppose each of the three packages from the previous example should have a
key named \PValue{coldcuts}. When used, a switch should be set in each of
the packages. For the \Package{salami} package, for example, this could look
like this:
\begin{lstcode}
\newif\if@salami@coldcuts
\DefineFamilyKey{butcher}%
{coldcuts}[true]{%
\expandafter\let\expandafter\if@salami@coldcuts
\csname if#1\endcsname
\FamilyKeyStateProcessed
}
\end{lstcode}
When called, the value will therefore be either \PValue{true} or
\PValue{false}. This example does not test for illegal values. Instead,
it is always reported that the key was processed completely and correctly.
If the key is used later, one of the permitted values, or no value, must be
used. In the second case, the default \PName{true} value will be used.
The definitions for the other packages are nearly identical. Only the string
``\texttt{salami}'' has to be replaced.
\end{Example}
%
\EndIndexGroup
\begin{Declaration}
\Macro{RelaxFamilyKey}\OParameter{member}\Parameter{family}%
\Parameter{key}
\end{Declaration}
If\ChangedAt{v3.15}{\Package{scrbase}} a \PName{key} has been previously
defined as a \PName{member} of a \PName{family}, that definition will be
cancelled. Afterwards the \PName{key} will no longer be defined for this
\PName{member} of the \PName{family}. You can use \Macro{RelaxFamilyKey} for a
\PName{key} that is not defined for this \PName{member} of the \PName{family}.
If you do not specify a \PName{member}, then the member
``\texttt{.}\Macro{@currname}\texttt{.}\Macro{@currext}'' is assumed, just as
with \DescRef{\LabelBase.cmd.DefineFamilyKey}. However, \Macro{RelaxFamilyKey}
is only rarely used while loading a package rather than at runtime. Therefore
the \PName{member} should usually be specified explicitly as well.%
\EndIndexGroup
\begin{Declaration}
\Macro{FamilyProcessOptions}\OParameter{member}\Parameter{family}
\end{Declaration}
In essence, extending keys from families to both families and family members
means that either keys or key-value pairs can be used as normal class or
package options. The \Macro{FamilyProcessOptions} command is an extension of
\Macro{ProcessOption*} from the \LaTeX{} kernel (see \cite{latex:clsguide},
which processes not only options declared with \Macro{DeclareOption}, but also
all keys of the given member. If you omit the optional argument
\PName{member}, the member
``\texttt{.}\Macro{@currname}\texttt{.}\Macro{@currext}'' is used.
One feature worth noting is that keys which are attached not to a family
member but to a family have an empty family member. Such keys are set before
the keys of the members.
\begin{Example}
If, in the packages from the previous example, you add the line
\begin{lstcode}
\FamilyProcessOptions{butcher}
\end{lstcode}
after you define the key, you can specify the \Option{coldcuts} option when
loading the package. If you specify the option globally in
\Macro{documentclass}, the option will be passed automatically to all three
packages if they are loaded later.
\end{Example}
Note\textnote{Attention!} that packages always process global options
before local options. While unknown global options result in an entry in the
\File{log} file and the option being otherwise ignored, unknown local
options result in an error message.
You can think of \Macro{FamilyProcessOptions} as an extension of either
\Macro{ProcessOption*} or the \PName{key=value} mechanism
of \Package{keyval}. Ultimately, with the help of
\Macro{FamilyProcessOptions}, \PName{key=value} pairs become options.%
As with\textnote{Attention!} \Macro{ProcessOptions},
\Macro{FamilyProcessOptions} must not be used while executing options code.
In particular, you cannot load packages while processing options.%
%
\EndIndexGroup
\begin{Declaration}
\Macro{BeforeFamilyProcessOptions}\OParameter{member}\Parameter{family}%
\Parameter{code}%
\end{Declaration}
Authors\ChangedAt{v3.18}{\Package{scrbase}} of wrapper classes in particular
sometimes need a hook to execute \PName{code} before
\DescRef{\LabelBase.cmd.FamilyProcessOptions}. The \Package{scrbase} package
provides such a hook, and you can add \PName{code} to it with
\Macro{BeforeFamilyProcessOptions}. The \PName{member} and \PName{family}
parameters are same as those of \DescRef{\LabelBase.cmd.FamilyProcessOptions}.
However, you can also add \PName{code} to the hook for families or members
that have not yet been defined.
Note that the hook of a family member is automatically deleted after it is
executed. But if you use an empty \PName{member}, this hook\Index{hook} will
be executed for every member of the \PName{family} and will not be deleted.
\begin{Example}
You are writing a \Package{smokedsausage} package that loads
\Package{mettwurst}. But you do not want to be able to set the
\Option{coldcut} option with this package. So you use
\Macro{BeforeFamilyProcessOptions} to deactivate that option before you load
the package:
\begin{lstcode}
\RequirePackage{scrbase}
\BeforeFamilyProcessOptions[.mettwurst.sty]{butcher}{%
\RelaxFamilyKey[.mettwurst.sty]{butcher}{coldcut}%
}
\RequirePackageWithOptions{mettwurst}
\end{lstcode}
If a user tries to load your package with the \Option{coldcut} option, the
\Package{mettwurst} package will throw an undefined option error. If
\Option{coldcut} is used as a global option, the \Package{mettwurst}
package will ignore it. But default settings inside \Package{mettwurst},
for example using \DescRef{\LabelBase.cmd.FamilyExecuteOptions} before
\DescRef{\LabelBase.cmd.FamilyProcessOptions} are not affected. Of course,
you can also insert your own default for \Package{smokedsausage} via
\Macro{BeforeFamilyProcessOptions} in \Package{mettwurst}.
\end{Example}
\EndIndexGroup
\begin{Declaration}
\Macro{FamilyExecuteOptions}\OParameter{member}\Parameter{family}%
\Parameter{options list}
\end{Declaration}
This command is an extension of \Macro{ExecuteOptions} from the \LaTeX{}
kernel (see \cite{latex:clsguide}). The command processes not only options
defined with \Macro{DeclareOption} but also all keys of the given
\PName{family}. If you omit the optional argument \Macro{member},
``\texttt{.}\Macro{@currname}\texttt{.}\Macro{@currext}'' is used.
One feature worth noting is that keys which are attached not to a family
member but to a family have an empty family member. Such keys are set before
the keys of the members.
\begin{Example}
Suppose the \Option{coldcuts} option should be set by default in the
previous examples. In this case only line
\begin{lstcode}
\FamilyExecuteOptions{butcher}{coldcuts}
\end{lstcode}
has to be added.
\end{Example}
If\ChangedAt{v3.20}{\Package{scrbase}} you call \Macro{FamilyExecuteOptions}
with an unknown option inside the \PName{options list}, you will get an error.
An exception to this rule occurs when the \PName{member} has an option called
\Option{@else@}. In this case, the \Option{@else@} option will be used instead
of the unknown one. The value passed to the \Option{@else@} option is the
unknown option with the value specified in the call. \KOMAScript{} itself uses
this feature, for example inside the definition of sectioning commands,
to evaluate the style option before all other attributes.
You can also use this command inside the code executed when processing the
option.%
%
\EndIndexGroup
\begin{Declaration}
\Macro{FamilyOptions}\Parameter{family}\Parameter{options list}%
\end{Declaration}
Unlike normal options defined with \Macro{DeclareOption}, the \PName{key}s can
also be set after loading a class or package. To do this, you call
\Macro{FamilyOptions}. The \PName{options list} has the form
\begin{flushleft}\vskip\dp\strutbox\begin{tabular}{l}
\PName{key}\texttt{=}\PName{value}\texttt{,}%
\PName{key}\texttt{=}\PName{value}\dots
\end{tabular}\vskip\dp\strutbox\end{flushleft}
after which the value assignment can be omitted for \PName{key}s that have a
defined default.
The statement sets the keys of all members of the specified family. If a
\PName{key} also exists as an attribute of the family itself, then the family
key is set first, followed by the member keys in the order in which they were
defined. If a given \PName{key} does not exist, either for the family or for
any member of the family, then \Macro{FamilyOptions} will throw an error. An
error also occurs if a \PName{key} exists for some members but each of those
members returns an error through \DescRef{\LabelBase.cmd.FamilyKeyState}.
\begin{Example}
You extend your butcher project with a \Package{sausagesalad} package. If
this package has been loaded, all sausage packages should generate cold
cuts:
\begin{lstcode}
\ProvidesPackage{sausagesalad}%
[2008/05/06 nonsense package]
\DefineFamily{butcher}
\DefineFamilyMember{butcher}
\FamilyProcessOptions{butcher}\relax
\FamilyOptions{butcher}{coldcuts}
\end{lstcode}
If no sausage package has yet been loaded, the undefined option
\Option{coldcuts} leads to an error message. You can avoid this by defining
a corresponding key for the package before the last line of the code above:
\begin{lstcode}
\DefineFamilyKey{butcher}%
{coldcuts}[true]{}%
\end{lstcode}
However, sausage packages loaded after \Package{sausagesalad} still do not
produce cold cuts. You can correct this by replacing the previous command
with:
\begin{lstcode}
\AtBeginDocument{%
\DefineFamiyKey[.sausagesalad.sty]%
{butcher}%
{coldcuts}[true]{}%
}
\DefineFamilyKey{butcher}%
{coldcuts}[true]{%
\AtBeginDocument{\FamilyOptions{butcher}%
{coldcuts=#1}}%
}%
\end{lstcode}
Thus, the option is defined during \Macro{begin}\PParameter{document} so
that it no longer functions for the \Package{sausagesalad} package. Because
\Macro{@currname} and \Macro{@currext} no longer contain the file name of
the package, you must use the optional argument of
\DescRef{\LabelBase.cmd.DefineFamilyKey}.
But until this redefinition is performed, it uses a definition that executes
the option again for the family and all its members during
\Macro{begin}\PParameter{document}, thus setting it for other sausage
packages. The delay in executing \Macro{FamilyOptions} is crucial here. For
one thing, it includes only the packages loaded afterwards. For another, it
ensures that its own \Option{coldcuts} option has already been redefined.
This avoids endless recursion.
\end{Example}
Like\ChangedAt{v3.27}{\Package{scrbase}}
\DescRef{\LabelBase.cmd.FamilyExecuteOptions}, \Macro{FamilyOptions} offers
special handling for an option named
\Option{@else@}\important{\Option{@else@}}. If a family member has such an
option, it will be executed whenever an option in the \PName{option list} is
unrecognized by the member. If the family itself defines an option
\Option{@else@}, it will only be called if neither the family nor any of its
members were able to fully process the given option by executing
\DescRef{\LabelBase.cmd.FamilyKeyStateProcessed}.%
\EndIndexGroup
\begin{Declaration}
\Macro{FamilyOption}\Parameter{family}%
\Parameter{option}\Parameter{value list}%
\end{Declaration}
In addition to options that have mutually exclusive values, there may be
options that can take multiple values at the same time. To use
\DescRef{\LabelBase.cmd.FamilyOptions} for that type of option, it would be
necessary to invoke the same option several times with different value
assignments. Instead, you can easily assign a whole list of values to a single
\PName{option} using \Macro{FamilyOption}. The \PName{value list} is a comma
separated list of values, also known as \emph{csv}:
%\begin{flushleft}\begin{tabular}{l}
\PName{value}\texttt{,}\PName{value}\dots
%\end{tabular}\end{flushleft}
Note in this context that you can use a comma in a value by putting the value
inside braces. This command's other functionality is the same previously
described for \DescRef{\LabelBase.cmd.FamilyOptions}.
\begin{Example}
The \Package{sausagesalad} package should have one more option to add
additional ingredients. Each of the ingredients sets a switch, as was done
previously for the cold cuts.
\begin{lstcode}
\newif\if@saladwith@onions
\newif\if@saladwith@gherkins
\newif\if@saladwith@chillies
\DefineFamilyKey{butcher}{ingredient}{%
\csname @saladwith@#1true\endcsname
}
\end{lstcode}
Here the three ingredients ``onions'', ``gherkins'', and ``chillies'' have
been defined. There is no error message for unknown ingredients.
For a salad with onions and gherkins, you can use
\begin{lstcode}
\FamilyOptions{butcher}{%
ingredient=onions,ingredient=gherkins}
\end{lstcode}
or simply
\begin{lstcode}
\FamilyOption{butcher}
{ingredient}{onions,gherkins}
\end{lstcode}
\end{Example}
An\ChangedAt{v3.27}{\Package{scrbase}} \Option{@else@} option is processed
in the same manner as with \DescRef{\LabelBase.cmd.FamilyOptions}.%
\EndIndexGroup
\begin{Declaration}
\Macro{AtEndOfFamilyOptions}\Parameter{action}%
\Macro{AtEndOfFamilyOptions*}\Parameter{action}%
\end{Declaration}
Sometimes\ChangedAt{v3.12}{\Package{scrbase}} it is useful to delay the
execution of an \PName{action} that is part of a value assignment to a key
until all assignments inside one
\DescRef{\LabelBase.cmd.FamilyProcessOptions}\IndexCmd{FamilyProcessOptions},
\DescRef{\LabelBase.cmd.FamilyExecuteOptions}\IndexCmd{FamilyExecuteOptions},
\DescRef{\LabelBase.cmd.FamilyOptions}\IndexCmd{FamilyOptions}, or
\DescRef{\LabelBase.cmd.FamilyOption}\IndexCmd{FamilyOptions} is finished.
You can do this using \Macro{AtEndOfFamilyOptions} or its starred
variant\ChangedAt{v3.23}{\Package{scrbase}} inside an option definition.
However, reporting failure states of \PName{action} is not possible with this
command, nor should it be used outside an option definition.
The two variants differ in case there are nested option definitions, when
executing an option requires further option calls. In this case all actions
specified by \Macro{AtEndOfFamilyOptions} will be executed when the innermost
option call returns. In contrast, the actions of \Macro{AtEndOfFamilyOptions*}
are not executed until the outermost option call returns.
However,\textnote{Attention!} the order of the actions of both commands is
emphatically undefined! It is not guaranteed that the action requested first
will be executed first, nor the converse.%
\EndIndexGroup
\begin{Declaration}
\Macro{FamilyBoolKey}\OParameter{member}\Parameter{family}%
\Parameter{key}\Parameter{switch name}%
\Macro{FamilySetBool}\Parameter{family}%
\Parameter{key}\Parameter{switch name}\Parameter{value}
\end{Declaration}
Boolean switches have been used several times in the previous examples. In the
example with \Option{coldcuts} option, the user had to assign either
\PValue{true} or \PValue{false} as a value. There was no error message if the
user provided the wrong value. Because boolean switches are a common use case,
you can easily define them with \Package{scrbase} using \Macro{FamilyBoolKey}.
The \PName{member}, \PName{family}, and \PName{key} arguments are the same as
those used by \DescRef{\LabelBase.cmd.DefineFamilyKey} (see
\DescPageRef{scrbase.cmd.DefineFamilyKey}). The \PName{switch name} is the
name of the switch without the prefix \Macro{if}. If a switch with this name
does not exist already, \Macro{FamilyBoolKey} will define it and initialize it
to \PName{false}. Internally, \Macro{FamilyBooKey} uses \Macro{FamilySetBool}
as the \PName{action} of \DescRef{\LabelBase.cmd.DefineFamilyKey}. The
\PName{default} for such an option is always \PValue{true}.
\Macro{FamilySetBool}, on the other hand, accepts \PValue{on} and
\PValue{yes}, in addition to \PName{true}, to turn the switch on, and
\PName{off} and \PName{no}, in addition to \PName{false}, to turn it off.
Unknown values will result in a call to
\DescRef{\LabelBase.cmd.FamilyUnknownKeyValue} with the arguments
\PName{family}, \PName{key}, and \PName{value}, which sets
\DescRef{\LabelBase.cmd.FamilyKeyState} accordingly. As a result, an error
message about an unknown value assignment is printed if necessary (see also
\DescPageRef{scrbase.cmd.FamilyUnknownKeyValue} and
\DescPageRef{scrbase.cmd.FamilyKeyState}).
\begin{Example}
The key \Option{coldcuts} should be defined more robustly in the sausage
packages. Additionally, all sausage packages should use the same key, so
that either all sausage packages will produce cold cuts or none will.
\begin{lstcode}
\FamilyBoolKey{butcher}{coldcuts}%
{@coldcuts}
\end{lstcode}
A test of whether to produce cold cuts would look like this:
\begin{lstcode}
\if@coldcuts
...
\else
...
\fi
\end{lstcode}
This would be the same in all three sausage packages, thereby
defining the attribute ``coldcuts'' as a family option:
\begin{lstcode}[moretexcs={define@key}]
\@ifundefined{if@coldcuts}{%
\expandafter\newif\csname if@coldcuts\endcsname
}{}%
\DefineFamilyKey[]{butcher}{coldcuts}[true]{%
\FamilySetBool{butcher}{coldcuts}%
{@coldcuts}%
{#1}%
}
\end{lstcode}
or shorter:
\begin{lstcode}
\FamilyBoolKey[]{butcher}{coldcuts}%
{@coldcuts}
\end{lstcode}
taking advantage of the treatment of empty family members as opposed to
omitting the optional argument explained on
\autopageref{explain:scrbase.macro.DefineFamilyKey}, which applies not only
to \DescRef{\LabelBase.cmd.DefineFamilyKey} but also for
\Macro{FamilyBoolKey}.
Since \DescRef{\LabelBase.cmd.FamilyKeyState} is already set by
\Macro{FamilySetBool}, you can check its status with the help of
\DescRef{\LabelBase.cmd.DefineFamilyKey}. For example, in the first case you
could add an equivalence test to \Macro{FamilySetBool} to perform additional
actions depending on whether \Macro{FamilySetBool} succeeded or not:
\begin{lstcode}
\ifx\FamilyKeyState\FamilyKeyStateProcessed
...
\else
...
\fi
\end{lstcode}
Note\textnote{Attention!} that it is essential to perform the test with
\Macro{ifx} at this point. Fully expanding tests like \Macro{ifstr} should
be avoided here. Depending on the current status and the comparison status,
they can lead to different error messages as well as incorrect results.
\end{Example}%
\EndIndexGroup
\begin{Declaration}
\Macro{FamilyInverseBoolKey}\OParameter{member}\Parameter{family}
\Parameter{key}\Parameter{switch name}
\Macro{FamilySetInverseBool}\Parameter{family}
\Parameter{key}\Parameter{switch name}
\Parameter{value}
\end{Declaration}
These\ChangedAt{v3.27}{\Package{scrbase}} two commands differ from
\DescRef{\LabelBase.cmd.FamilyBoolKey} and
\DescRef{\LabelBase.cmd.FamilySetBool}, respectively, only in that the
logic is inverted. This means that the values \PValue{true}, \PValue{yes}, and
\PValue{on} set the boolean switch given by \PName{switch name} to
\Macro{iffalse} and therefore deactivate it. The values \PValue{false},
\PValue{no}, and \PValue{off} set the boolean switch to \Macro{iftrue} and
therefore activate it.%
\EndIndexGroup
\begin{Declaration}
\Macro{FamilyNumericalKey}\OParameter{member}\Parameter{family}%
\Parameter{key}%
\OParameter{default}\Parameter{command}%
\Parameter{value list}%
\Macro{FamilySetNumerical}\Parameter{family}\Parameter{key}%
\Parameter{command}\Parameter{value list}%
\Parameter{value}
\end{Declaration}
While switches can accept only two values, there are also keys that recognize
several values. For example an alignment can be not just left or not-left, but
left, centred, or right. Internally, such differentiation is often made using
\Macro{ifcase}. This \TeX{} command expects a numerical value. Therefore in
\Package{scrbase} the command to define a macro by a \PName{key} has been
named \Macro{FamilyNumericalKey}. The \PName{value list} has the form:
%\begin{flushleft}\vskip\dp\strutbox\begin{tabular}{l}
\Parameter{value}\Parameter{definition}\texttt{,}\linebreak[1]%
\Parameter{value}\Parameter{definition}\texttt{,}~\dots
%\end{tabular}\vskip\dp\strutbox\end{flushleft}
The \PName{value list} defines not just the values permitted for the
\PName{key}. For each \PName{value}, the \PName{definition} of the macro
\Macro{\PName{command}} also is given. Usually, the \PName{definition} is just
a numerical value. Although other content is possible, there is currently a
restriction that the \PName{definition} must be fully expandable, and it will
be expanded during the assignment.
\begin{Example}
The sausage for the sausage salad can be cut differently. For example, the
cold cuts could simply remain uncut or be cut into thick or thin slices.
This information should be stored in the command \Macro{cuthow}.
\begin{lstcode}
\FamilyNumericalKey{butcher}%
{saladcut}{cuthow}{%
{none}{none},{no}{none},{not}{none}%
{thick}{thick},%
{thin}{thin}%
}
\end{lstcode}
Not cutting anything can be selected by
\begin{lstcode}
\FamilyOptions{butcher}{saladcut=none}
\end{lstcode}
or
\begin{lstcode}
\FamilyOptions{butcher}{saladcut=no}
\end{lstcode}
or
\begin{lstcode}
\FamilyOptions{butcher}{saladcut=not}
\end{lstcode}
In all three cases \Macro{cuthow} would be defined with the content
\PValue{none}. It can be useful to provide several values for the same
result, as shown in this example.
Now it's very likely that the manner of cutting will not be printed but
should be evaluated later. In this case, a textual definition would be
rather impractical. If the key is defined like this:
\begin{lstcode}
\FamilyNumericalKey{butcher}%
{saladcut}{cuthow}{%
{none}{0},{no}{0},{not}{0}%
{thick}{1},%
{thin}{2}%
}
\end{lstcode}
then you can use a condition like the following:
\begin{lstcode}
\ifcase\cuthow
% uncut
\or
% thickly cut
\else
% thinly cut
\fi
\end{lstcode}
\end{Example}
Internally, \Macro{FamilyNumericalKey} uses \Macro{FamilySetNumerical} as the
\PName{action} of \DescRef{\LabelBase.cmd.DefineFamilyKey}. If an unknown
value is assigned to such a key, \Macro{FamilySetNumerical} will call
\DescRef{\LabelBase.cmd.FamilyUnknownKeyValue} with the \PName{family},
\PName{key} and \PName{value} arguments. This leads to an error signalled with
the \DescRef{\LabelBase.cmd.FamilyKeyStateUnknownValue} status in
\DescRef{\LabelBase.cmd.FamilyKeyState}. Similarly, when calling
\Macro{FamilySetNumerical} the success is signalled via
\DescRef{\LabelBase.cmd.FamilyKeyStateProcessed} in
\DescRef{\LabelBase.cmd.FamilyKeyState}.%
%
\EndIndexGroup
\begin{Declaration}
\Macro{FamilyCounterKey}\OParameter{member}\Parameter{family}%
\Parameter{key}%
\OParameter{default}\Parameter{\LaTeX{} counter}%
\Macro{FamilySetCounter}\Parameter{family}%
\Parameter{key}\Parameter{\LaTeX{} counter}\Parameter{value}
\end{Declaration}
While\ChangedAt{v3.12}{\Package{scrbase}}
\DescRef{\LabelBase.cmd.FamilyNumericalKey} defines a macro in which a numeric
value corresponds to a symbolic value, there are, of course, circumstances
when a \PName{key} directly represents a \PName{\LaTeX{} counter} to which a
numeric value should be assigned immediately. For this case, you can use
\Macro{FamilyCounterKey}, which calls \Macro{FamilySetCounter} internally.
There are some basic tests of the \PName{value} argument to determine if the
\PName{value} argument appears to be suitable for assignment to a counter. The
assignment will only be made if these tests succeed. However, not all errors
can be detected here, so an incorrect assignment can also lead to an error
message from \TeX{} itself. Errors that are detected, however, are signalled
by \DescRef{\LabelBase.cmd.FamilyKeyStateUnknownValue}.
If\ChangedAt{v3.15}{\Package{scrbase}} the value is omitted, the
\PName{default} is used instead. If there is no \PName{default}, the
\PName{key} can be used only with an explicit value.%
\EndIndexGroup
\begin{Declaration}
\Macro{FamilyCounterMacroKey}\OParameter{member}\Parameter{family}%
\Parameter{key}%
\OParameter{default}\Parameter{macro}%
\Macro{FamilySetCounterMacro}\Parameter{family}%
\Parameter{key}\Parameter{macro}\Parameter{value}%
\end{Declaration}
These\ChangedAt{v3.12}{\Package{scrbase}} two commands differ from the
previously described \DescRef{\LabelBase.cmd.FamilyCounterKey} and
\DescRef{\LabelBase.cmd.FamilySetCounter} only by the fact that they do not
assign a \PName{value} to a \LaTeX{} counter, but define a \Macro{macro} with
the \PName{value}. This \PName{value} is locally assigned to a counter and
then its expanded value is used. Therefore, its value at the time the option
is called applies.%
\EndIndexGroup
\begin{Declaration}
\Macro{FamilyLengthKey}\OParameter{member}\Parameter{family}
\Parameter{key}
\OParameter{default}\Parameter{length}
\Macro{FamilySetLength}\Parameter{family}
\Parameter{key}\Parameter{length}\Parameter{value}
\Macro{FamilyLengthMacroKey}\OParameter{member}\Parameter{family}
\Parameter{key}
\OParameter{default}\Parameter{macro}
\Macro{FamilySetLengthMacro}\Parameter{family}
\Parameter{key}\Parameter{macro}
\Parameter{value}
\Macro{FamilyUseLengthMacroKey}\OParameter{member}\Parameter{family}
\Parameter{key}
\OParameter{default}\Parameter{macro}
\Macro{FamilySetUseLengthMacro}\Parameter{family}
\Parameter{key}\Parameter{macro}
\Parameter{value}
\end{Declaration}
With\ChangedAt{v3.12}{\Package{scrbase}} \Macro{FamilyLengthKey}, you can
define a \PName{key} that represents a \PName{length}. It does not matter
whether the \PName{length} is a \LaTeX{} length, a \TeX{} skip, or a \TeX{}
dimension. Internally the \PName{length} will be set to the \PName{value}
using \Macro{FamilySetLength}. There are some basic tests to decide whether
this \PName{value} is valid to assign to \PName{length}. The assignment will
only take place if these tests succeed. However, not all errors can be
detected, so an inaccurate \PName{value} can still result in a \TeX{} error.
Errors that are detected, however, are signalled by
\DescRef{\LabelBase.cmd.FamilyKeyStateUnknownValue}.
If\ChangedAt{v3.15}{\Package{scrbase}} the value is omitted, the
\PName{default} is used instead. If there is no \PName{default}, the
\PName{key} can be used only with an explicit value.
When you use \Macro{FamilyLengthMacroKey} and \Macro{FamilySetLengthMacroKey},
or \Macro{FamilySetLengthMacro} and \Macro{FamilySetUseLengthMacro}, the
\PName{value} is stored not in a \PName{length} but in a
\PName{macro}. \Macro{FamilyLengthMacroKey} and
\Macro{FamilySetLengthMacroKey} define the \PName{macro} to be the
\PName{value} as evaluated at the point of definition, similar to
\Macro{setlength}. In contrast,
\Macro{FamilyUseLengthMacroKey}\ChangedAt{v3.20}{\Package{scrbase}} and
\Macro{FamilySetUseLengthMacroKey} store the \PName{value} directly, and
so the \PName{value} is reevaluated each time the \PName{macro} is used.%
\EndIndexGroup
\begin{Declaration}
\Macro{FamilyStringKey}\OParameter{member}\Parameter{family}%
\Parameter{key}%
\OParameter{default}\Parameter{command}
\Macro{FamilyCSKey}\OParameter{member}\Parameter{family}%
\Parameter{key}%
\OParameter{default}\Parameter{command name}
\end{Declaration}
This defines\ChangedAt{v3.08}{\Package{scrbase}} a \PName{key} that accepts
any value. The value will be stored in the specified \Macro{command}. If there
is no optional argument for the \PName{default}, \Macro{FamilyStringKey} is
the same as:
\begin{lstcode}[escapeinside=`']
\DefineFamilyKey[`\PName{member}']{`\PName{family}'}{`\PName{key}'}
{\def`\PName{command}'{#1}}
\end{lstcode}
If you use the optional argument \PName{default}, \Macro{FamilyStringKey}
corresponds to:
\begin{lstcode}[escapeinside=`']
\DefineFamilyKey[`\PName{member}']{`\PName{family}'}{`\PName{key}'}
[`\PName{default}']
{\def`\PName{command}'{#1}\FamilyKeyStateProcessed}
\end{lstcode}
\begin{Example}
By default 250\Unit{g} of sausage salad should be produced. However, the
amount should be configurable by an option. To do so, the quantity to be
created is stored in the macro \Macro{saladweight}. The option to change
the weight should also be called \PValue{saladweight}:
\begin{lstcode}
\newcommand*{\saladweight}{250g}
\FamilyStringKey{butcher}%
{saladweight}[250g]{\saladweight}
\end{lstcode}
To switch back to the default weight after changing it, you can simply
call the option without the weight:
\begin{lstcode}
\FamilyOptions{butcher}{saladweight}
\end{lstcode}
This is possible because the default quantity was also set as the default
value in the definition.
\end{Example}
In this case, there are no unknown values because all values are simply used
for a macro definition. Note, however, that paragraph breaks are not allowed
when assigning a value to the key.
In contrast\ChangedAt{v3.25}{\Package{scrbase}} to \Macro{FamilyStringKey},
the \Macro{FamilyCSKey} command expects for the final argument not a macro but
only the name of a command, for example \PParameter{saladweight} instead of
\PParameter{\Macro{saladweight}}.%
%
\EndIndexGroup
\begin{Declaration}
\Macro{FamilyUnknownKeyValue}\Parameter{family}\Parameter{key}%
\Parameter{value}\Parameter{value list}%
\end{Declaration}
The command \Macro{FamilyUnknownKeyValue} throws an error message due to an
unknown or illegal values by means of \DescRef{\LabelBase.cmd.FamilyKeyState}.
The \PName{value list} is a comma separated list of permissible values in the
form
%\begin{flushleft}\vskip\dp\strutbox\begin{tabular}{l}
`\PName{value}'\texttt{,} `\PName{value}' \dots
%\end{tabular}\vskip\dp\strutbox\end{flushleft}
However\ChangedAt{v3.12}{\Package{scrbase}}, the \PName{value list} is
currently not evaluated by \Package{scrbase}.
\begin{Example}
The user should now also be able to select whether the cold cuts should be
cut thick or thin. Thick should be the default setting, which should be used
even if the user does not specify how to cut the coldcuts.
\begin{lstcode}
\@ifundefined{if@thincut}{%
\expandafter
\newif\csname if@thincut\endcsname}{}%
\@ifundefined{if@coldcuts}{%
\expandafter
\newif\csname if@coldcuts\endcsname}{}
\DefineFamilyKey{butcher}%
{coldcuts}[true]{%
\FamilySetBool{butcher}{coldcuts}%
{@coldcuts}%
{#1}%
\ifx\FamilyKeyState\FamilyKeyStateProcessed
\@thincutfalse
\else
\Ifstr{#1}{thin}{%
\@coltcutstrue
\@finecuttrue
\FamilyKeyStateProcessed
}{%
\FamilyUnknownKeyValue{butcher}%
{coldcuts}%
{#1}{%
`true', `on', `yes',
`false`, `off`, `no',
`thin'%
}%
}%
\fi
}%
\end{lstcode}
First we try to set the boolean coldcuts switch using
\DescRef{\LabelBase.cmd.FamilySetBool}. If this succeeds, i.\,e. if
\DescRef{\LabelBase.cmd.FamilyKeyState} corresponds to
\DescRef{\LabelBase.cmd.FamilyKeyStateProcessed}, thincut will be
deactivated. Otherwise, we check if the value is equal to \PValue{thin}
rather than one of the valid values for a boolean switch. In this case, both
coldcuts and thincut are activated and the state will be switched to
\DescRef{\LabelBase.cmd.FamilyKeyStateProcessed}. If the previous test
fails, the error state signalled by \DescRef{\LabelBase.cmd.FamilySetBool}
is reset to \DescRef{\LabelBase.cmd.FamilyKeyStateUnknownValue}. The list of
the permissible values will be added to it. However, since this list is no
longer used, it would have been easy to skip the call to
\Macro{FamilyUnknownKeyValue} in the example and thus assume the error
status of \DescRef{\LabelBase.cmd.FamilySetBool}.
The \Macro{ifstr} command used in the test is explained on
\DescPageRef{scrbase.cmd.Ifstr} in \autoref{sec:scrbase.if}.
\end{Example}
%
\EndIndexGroup
\section{Conditional Execution}
\seclabel{if}
The \Package{scrbase} package provides several commands for conditional
execution. Mostly it does not rely on the \TeX{} syntax of conditionals such
as
\begin{lstcode}
\iftrue
...
\else
...
\fi
\end{lstcode}
but uses the \LaTeX{} syntax with arguments similar to those used by \LaTeX{}
commands like \Macro{IfFileExists}, \Macro{@ifundefined},
\Macro{@ifpackageloaded}, and many others.
% TODO: Fix translation (note: this text does not really correspond to the
% German manual but there is a similar note at the (not free) German book
From \KOMAScript~3.28, following a recommendation from \LaTeX{} team members,
\Package{scrbase} does not longer use \Macro{if\dots} but \Macro{If\dots} for
commands that expect an argument instead of using the \TeX{}
syntax. Some commands from prior versions of \KOMAScript{} have been
removed. You may use package \Package{iftex} (see \cite{package:iftex}) to
replace the functionality. Others have been renamed.
% :ODOT
\begin{Declaration}
\Macro{Ifundefinedorrelax}%
\Parameter{name}\Parameter{then code}\Parameter{else code}
\end{Declaration}
This\ChangedAt{v3.28}{\Package{scrbase}} command works like
\Macro{@ifundefined} from the \LaTeX{} kernel (see \cite{latex:source2e}). So
the \PName{then code} is executed if \PName{name} is the name of a
command that is currently either not defined or \Macro{relax}. Otherwise, the
\PName{else code} is executed. Unlike \Macro{@ifundefined}, no hash
memory is allocated nor is \Macro{\PName{Name}} set to \Macro{relax} if
\Macro{\PName{name}} was previously undefined.%
\EndIndexGroup
\begin{Declaration}
\Macro{Ifnotundefined}\Parameter{name}%
\Parameter{then code}\Parameter{else code}
\end{Declaration}
If\ChangedAt{v3.28}{\Package{scrbase}} the command with the given name has
already been defined, the \PName{then code} is executed. Otherwise, the
\PName{else code} is executed. Since \eTeX{} already has a primitive
\Macro{ifdefined}, this somewhat unwieldy name, unfortunately, had to be
chosen. There is no corresponding internal command.%
\EndIndexGroup
\begin{Declaration}
\Macro{Ifstr}\Parameter{string 1}\Parameter{string 2}%
\Parameter{then code}\Parameter{else code}
\end{Declaration}
Both\ChangedAt{v3.28}{\Package{scrbase}} \PName{string} arguments are expanded
and then compared. If the expansions are the same, the \PName{then code} is
executed. Otherwise the \PName{else code} is executed. There is no
corresponding internal command.
%
\EndIndexGroup
\begin{Declaration}
\Macro{Ifstrstart}\Parameter{string 1}\Parameter{string 2}%
\Parameter{then code}\Parameter{else code}
\end{Declaration}
Both\ChangedAt{v3.12}{\Package{scrbase}}\ChangedAt{v3.28}{\Package{scrbase}}
\PName{string} arguments are expanded and then compared. If \PName{string 1},
apart from white space, begins with \PName{string 2}, the \PName{then code} is
executed. Otherwise, the \PName{else code} is executed. There is no
corresponding internal command.%
\EndIndexGroup
\begin{Declaration}
\Macro{IfArgIsEmpty}\Parameter{argument}
\Parameter{then code}\Parameter{else code}
\end{Declaration}
If\ChangedAt{v3.19}{\Package{scrbase}} the \PName{argument} is empty, the
\PName{then code} is executed, otherwise the \PName{else code} is
executed. Even one whitespace character is considered non-empty. Since the
\PName{argument} is not expanded, macros that expand to an empty result are
also considered to be a non-empty \PName{argument}. The same applies to
\Macro{relax} or undefined macros.%
\EndIndexGroup
\iffalse % internal
\begin{Declaration}
\Macro{scr@ifluatex}
\Parameter{then code}\Parameter{else code}
\end{Declaration}
If\ChangedAt{v3.21}{\Package{scrbase}} you use lua\TeX{}, the \PName{then
code} will be executed. Otherwise, the \PName{else code} will be executed.
\iftrue% Umbruchkorrekturtext
This test is rarely useful. %
\fi%
As a rule, it is better to test directly for the command you want.
There\textnote{Attention!} is no user equivalent for this instruction. Use the
\Package{ifluatex}\important{\Package{ifluatex}} package instead (see
\cite{package:ifluatex}).%
\EndIndexGroup
\fi
\iffalse% It makes no sense to document this instruction yet
\begin{Declaration}
\Macro{scr@ifpdforluatex}
\Parameter{then code}\Parameter{else code}
\end{Declaration}
Until lua\TeX~0.85, it was mostly irrelevant whether you used pdf\TeX{} or
lua\TeX{}. This command, which executes the \PName{then code} in both cases,
derives from that fact. If neither pdf\TeX{} nor lua\TeX{} is used, the
\PName{else code} will be executed. Since version~0.85, lua\TeX{} has given up
compatibility with many of its commands. Therefore this distinction is no
longer useful in practice and is no longer used by \KOMAScript{} itself. There
is no user equivalent of this statement.%
\EndIndexGroup
\fi
\iffalse % internal
\begin{Declaration}
\Macro{scr@ifpdftex}%
\Parameter{then code}\Parameter{else code}%
\end{Declaration}
If you use pdf\TeX{}, the \PName{then code} will be executed. Otherwise, the
\PName{else code} will be executed. It does not matter whether a PDF-file is
actually generated or not. This test is rarely useful. As a rule, you should
test directly for the command you want instead.%
\EndIndexGroup
\fi
\iffalse % internal
\begin{Declaration}
\Macro{scr@ifVTeX}%
\Parameter{then code}\Parameter{else code}%
\end{Declaration}
If you use V\TeX{}, the \PName{then code} is executed. Otherwise, the
\PName{else code} is executed. This test is seldom useful. As a rule,
you should test directly for the command you want instead.%
%
\EndIndexGroup
\fi
\begin{Declaration}
\Macro{Ifpdfoutput}%
\Parameter{then code}\Parameter{else code}
\end{Declaration}
If\ChangedAt{v3.28}{\Package{scrbase}} a PDF file is generated, the
\PName{then code} is executed. Otherwise, the \PName{else code} is
executed. It does not matter whether PDF file is created using lua\TeX{},
pdf\TeX{}, or V\TeX{}, or \XeTeX{}.%
\EndIndexGroup
\begin{Declaration}
\Macro{Ifpsoutput}%
\Parameter{then code}\Parameter{else code}
\end{Declaration}
If\ChangedAt{v3.28}{\Package{scrbase}} a PostScript file is generated, the
\PName{then code} is executed. Otherwise, the \PName{else code} is
executed. V\TeX{} can generate PostScript directly, which is recognized
here. However, if V\TeX{} is not used but the switch \Macro{if@dvips} has been
defined, the decision depends on that switch. \KOMAScript{} provides
\Macro{if@dvips} in
\hyperref[cha:typearea]{\Package{typearea}}\IndexPackage{typearea}%
\IndexCmd{if@dvips}.
%
\EndIndexGroup
\begin{Declaration}
\Macro{Ifdvioutput}%
\Parameter{then code}\Parameter{else code}
\end{Declaration}
If\ChangedAt{v3.28}{\Package{scrbase}} a DVI-file is generated, the
\PName{then code} is executed. Otherwise, the \PName{else code} is
executed. A DVI file is always assumed to be generated if no direct output of
a PDF file or a PostScript file can be detected.%
\EndIndexGroup
\begin{Declaration}
\Macro{Ifisdimen}\Parameter{expression}%
\Parameter{then code}\Parameter{else code}
\end{Declaration}
If\ChangedAt{v3.12}{\Package{scrbase}}\ChangedAt{v3.28}{\Package{scrbase}}
\PName{expression} expands to a \Macro{dimen}, i.\,e. a \TeX{} length
register, the \PName{then code} is executed. Otherwise the \PName{else
code} is executed. The command is not completely expandable, and there
is no corresponding internal command.%
\EndIndexGroup
\begin{Declaration}
\Macro{Ifisdimension}\Parameter{expression}%
\Parameter{then code}\Parameter{else code}
\end{Declaration}
If\ChangedAt{v3.12}{\Package{scrbase}}\ChangedAt{v3.28}{\Package{scrbase}}
\PName{expression} expands to something syntactically equivalent to a length,
the \PName{then code} is executed. Otherwise the \PName{else code} is
executed. Note\textnote{Attention!} that unknown units cause an error
message. The command is not completely expandable, and there is no
corresponding internal command.%
\EndIndexGroup
\begin{Declaration}
\Macro{Ifdimen}\Parameter{string}%
\Parameter{then code}\Parameter{else code}
\end{Declaration}
The \PName{then code}\ChangedAt{v3.28}{\Package{scrbase}} is executed if
the first-order expansion of \PName{string} consists of digits and a valid
length unit. Otherwise, the \PName{else code} is used. There is no
corresponding internal command.%
\EndIndexGroup
\begin{Declaration}
\Macro{Ifisdimexpr}\Parameter{expression}%
\Parameter{then code}\Parameter{else code}
\end{Declaration}
If\ChangedAt{v3.12}{\Package{scrbase}}\ChangedAt{v3.28}{\Package{scrbase}}
\PName{expression} expands to an \eTeX{} \Macro{dimexpr}\IndexCmd{dimexpr},
the \PName{then code} is executed. Otherwise, the \PName{else code} is
executed. Note\textnote{Attention!} that illegal expressions result in
error messages. The command is not completely expandable, and there is no
corresponding internal command.%
\EndIndexGroup
\begin{Declaration}
\Macro{Ifisskip}\Parameter{expression}%
\Parameter{then code}\Parameter{else code}
\end{Declaration}
If\ChangedAt{v3.12}{\Package{scrbase}}\ChangedAt{v3.28}{\Package{scrbase}}
\PName{expression} expands to a \Macro{skip}, i.\,e. a \TeX{} distance, the
\PName{then code} is executed. Otherwise, the \PName{else code} is
executed. The command is not completely expandable, and there is no
corresponding internal command.%
\EndIndexGroup
\begin{Declaration}
\Macro{Ifisglue}\Parameter{expression}%
\Parameter{then code}\Parameter{else code}
\end{Declaration}
If\ChangedAt{v3.12}{\Package{scrbase}}\ChangedAt{v3.28}{\Package{scrbase}}
\PName{expression} expands to something syntactically equivalent of the value
of a skip, the \PName{then code} is executed. Otherwise, the \PName{else
code} is executed. Note\textnote{Attention!} that invalid units
result in an error message. The command is not completely expandable, and
there is no corresponding internal command.%
\EndIndexGroup
\begin{Declaration}
\Macro{Ifisglueexpr}\Parameter{expression}%
\Parameter{then code}\Parameter{else code}
\end{Declaration}
If\ChangedAt{v3.12}{\Package{scrbase}}\ChangedAt{v3.28}{\Package{scrbase}}
\PName{expression} expands to a \Macro{glueexpr}, i.\,e. an \eTeX{} distance
expression, the \PName{then code} is executed. Otherwise, the \PName{else
code} is executed. Note,\textnote{Attention!} that illegal expressions
result in error messages. The command is not completely expandable, and
there is no corresponding internal command.%
\EndIndexGroup
\begin{Declaration}
\Macro{Ifiscounter}\Parameter{counter}%
\Parameter{then code}\Parameter{else code}
\end{Declaration}
If\ChangedAt{v3.12}{\Package{scrbase}}\ChangedAt{v3.28}{\Package{scrbase}}
\PName{counter} is defined as a \LaTeX{} counter, the \PName{then code} is
executed. Otherwise, the \PName{else code} is executed. The command is
not completely expandable, and there is no corresponding internal command.%
\EndIndexGroup
\begin{Declaration}
\Macro{Ifiscount}\Parameter{count}%
\Parameter{then code}\Parameter{else code}
\end{Declaration}
If\ChangedAt{v3.12}{\Package{scrbase}}\ChangedAt{v3.28}{\Package{scrbase}}
\PName{count} expands to a \Macro{count}, i.\,e. a \TeX{} counter, the
\PName{then code} is executed. Otherwise, the \PName{else code} is
executed. The command is not completely expandable, and there is no
corresponding internal command. For tests of \LaTeX{} counters, see
\DescRef{\LabelBase.cmd.Ifiscounter}.%
\EndIndexGroup
\begin{Declaration}
\Macro{Ifisinteger}\Parameter{expression}%
\Parameter{then code}\Parameter{else code}
\end{Declaration}
If\ChangedAt{v3.12}{\Package{scrbase}}\ChangedAt{v3.28}{\Package{scrbase}}
\PName{expression} expands to something syntactically equivalent to of the
value of a counter, i.\,e. a negative or positive integer, the \PName{then
code} is executed. Otherwise, the \PName{else code} is
executed. The command is not completely expandable, and there is no
corresponding internal command.%
\EndIndexGroup
\begin{Declaration}
\Macro{Ifnumber}\Parameter{string}%
\Parameter{then code}\Parameter{else code}
\end{Declaration}
The\ChangedAt{v3.28}{\Package{scrbase}} \PName{then code} is executed if
the first-order expansion of \PName{string} consists only of
digits. Otherwise, the \PName{else code} is used. There is no
corresponding internal command.
%
\EndIndexGroup
\begin{Declaration}
\Macro{Ifisnumexpr}\Parameter{expression}%
\Parameter{then code}\Parameter{else code}
\end{Declaration}
If\ChangedAt{v3.12}{\Package{scrbase}}\ChangedAt{v3.28}{\Package{scrbase}}
\PName{expression} expands to a \Macro{numexpr}, i.\,e. an \eTeX{} number
expression, the \PName{then code} is executed. Otherwise, the \PName{else
code} is executed. Note\textnote{Attention!} that illegal expressions
result in error messages. The command is not completely expandable, and
there is no corresponding internal command.%
\EndIndexGroup
\begin{Declaration}
\Macro{IfActiveMkBoth}\Parameter{then code}\Parameter{else code}
\end{Declaration}
The\ChangedAt{v3.27}{\Package{scrbase}} \LaTeX{} kernel uses
\DescRef{scrlayer.cmd.@mkboth}\important{\Macro{@mkboth}}\IndexCmd{@mkboth} to
distinguish between automatic and manual running heads. Usually, it sets both
marks with automatic running heads. With manual running heads, it does not set
any mark. To determine whether automatic running heads are active, many
packages compare \DescRef{scrlayer.cmd.@mkboth} with either
\DescRef{maincls.cmd.markboth}\IndexCmd{markboth} or \Macro{@gobbletwo}. But
this does not account for all cases in which \DescRef{scrlayer.cmd.@mkboth}
may be redefined. Therefore \Macro{IfActiveMkBoth} tests if
\DescRef{scrlayer.cmd.@mkboth} would actually set a mark, even when
\Macro{marks} appears in the definition of \DescRef{scrlayer.cmd.@mkboth}. If
such an active \DescRef{scrlayer.cmd.@mkboth} is detected, the
\PName{then code} is executed. In all other cases, the \PName{else code} is
used.%
\begin{Example}
For example, suppose you want to set the right mark if and only if
automatic running heads are used, e.\,g., the pagestyle
\PageStyle{headings}\IndexPagestyle{headings}. For a first attempt,
you might use:
\begin{lstcode}
\ifx\@mkboth\markboth \markright{running head}\fi
\end{lstcode}
Later you discover that some package does not use the usual
\begin{lstcode}
\let\@mkboth\markboth
\end{lstcode}
but
\begin{lstcode}
\renewcommand{\@mkboth}{\markboth}
\end{lstcode}
to activate automatic running heads. Because of this, your comparison always
fails and never calls \DescRef{maincls.cmd.markright}. To solve this, you
try the following change:
\begin{lstcode}
\ifx\@mkboth\@gobbletwo\else \markright{running head}\fi
\end{lstcode}
Unfortunately, now \DescRef{maincls.cmd.markright} is also called for
manual running heads, because someone has defined
\begin{lstcode}
\renewcommand{\@mkboth}[2]{%
\typeout{DEBUG: ignoring running head setting}%
}
\end{lstcode}
for this case.
Fortunately, both problems are easy to solve with \Package{scrbase}:
\begin{lstcode}
\IfActiveMkBoth{\markright{Kolumnentitel}}{}
\end{lstcode}%
\end{Example}
By the way, an even simpler solution for the problem in the example
would be to use \DescRef{scrlayer.cmd.@mkright} from package
\hyperref[cha:scrlayer]{\Package{scrlayer}} (see
\autoref{sec:scrlayer.pagestyle.content},
\DescPageRef{scrlayer.cmd.@mkright}).%
\EndIndexGroup
\begin{Declaration}
\Macro{if@atdocument}\ \PName{then code}\ %
\textMacro{else}\ \PName{else code}\ \textMacro{fi}
\end{Declaration}
This conditional command intentionally exists only as an internal command. In
the document preamble, \Macro{if@atdocument} corresponds to \Macro{iffalse}.
After \Macro{begin}\PParameter{document}, it corresponds to \Macro{iftrue}.
Authors of classes and packages may find this command useful if a command
should behave differently depending on whether it is used in the preamble or
inside document body. Note\textnote{Attention!} that this command is a
condition using \TeX{} syntax and not \LaTeX{} syntax!
%
\EndIndexGroup
\section{Defining Language-Dependent Terms}
\seclabel{languageSupport}
\BeginIndexGroup
\BeginIndex{}{language>definition}
\index{language>dependent terms|see{language definition}}
\index{terms>language-dependent|see{language definition}}
Beginners often find it difficult to change language-dependent terms
\Macro{listfigurename}\IndexCmd{listfigurename}, by default usually ``List of
Figures.'' For example, if these are simply redefined with
\Macro{renewcommand} in the document preamble, they will not survive a later
change of language. If you use \Package{babel}\IndexCmd{babel}, the
redefinition in the preamble is overwritten with
\Macro{begin}\PParameter{document}.
To define or change language-dependent terms, you normally have to redefine
commands like \Macro{captionsenglish} so that the new or redefined terms are
defined in addition to the previous terms. This is made more difficult by the
fact that some packages like \Package{german}\IndexPackage{german} or
\Package{ngerman}\IndexPackage{ngerman} redefine those settings when they are
loaded. These definitions, unfortunately, occur in a way that undoes all the
previous changes. For this reason, it makes sense to delay changes until
\Macro{begin}\PParameter{document} by using \Macro{AtBeginDocument}, that is,
after all packages have been loaded. A user can also use
\Macro{AtBeginDocument} or redefine the language-dependent terms not in the
preamble but after \Macro{begin}\PParameter{document}.
Adding further to the difficulty, some packages define additional
language-dependent terms in \Macro{captions\PName{language}}, while others use
\Macro{extras\PName{language}}. So the user must understand the commands very
well in order to use the correct one in the right way.
The \Package{scrbase} package therefore provides additional commands to define
or modify language-dependent terms, relieving the user of many of these
problems. These commands also let you simultaneously define or change the
language-dependent terms of several dialects or forms of a language.
\begin{Declaration}
\Macro{defcaptionname}%
\Parameter{language list}\Parameter{term}\Parameter{definition}%
\Macro{providecaptionname}%
\Parameter{language list}\Parameter{term}\Parameter{definition}%
\Macro{newcaptionname}%
\Parameter{language list}\Parameter{term}\Parameter{definition}%
\Macro{renewcaptionname}%
\Parameter{language list}\Parameter{term}\Parameter{definition}%
\Macro{defcaptionname*}%
\Parameter{language list}\Parameter{term}\Parameter{definition}%
\Macro{providecaptionname*}%
\Parameter{language list}\Parameter{term}\Parameter{definition}%
\Macro{newcaptionname*}%
\Parameter{language list}\Parameter{term}\Parameter{definition}%
\Macro{renewcaptionname*}%
\Parameter{language list}\Parameter{term}\Parameter{definition}
\end{Declaration}
With these four commands and their starred variants, you can assign a
\PName{definition} for a particular language to a \PName{term}. Several
languages can be concatenated with comma in the \PName{language list}.
The \PName{term} is always a macro. The commands differ depending on whether a
given language or a \PName{term} within a given language is already defined at
the time the command is called.
If a language is not defined, \Macro{providecaptionname} does nothing other
than write a message to the log file. This happens only once for each
language. If a language is defined but does not yet contain a corresponding
\PName{term}, it will be defined using \PName{definition}. However, the
\PName{term} will not be redefined if the language already has such a
definition; instead, an appropriate message is written to the log file.
On the other hand, if a language has not yet been defined,
\Macro{newcaptionname} defines a new language command will be created. For the
language \PValue{USenglish}, for example, this would be the language command
\Macro{captionsUSenglish}. This definition will also be noted in the log file.
If \PName{term} is not yet defined in this language, it will be defined using
\PName{definition}. If the \PName{term} already exists in a language, an error
message is issued.
The \Macro{renewcaptionname} command behaves still differently. If a language
is undefined, an error message is issued. If the \PName{term} is not defined
in this language, an error message is also issued. If the \PName{term} is
defined in the language, it will be redefined to \PName{definition}.
The\ChangedAt{v3.12}{\Package{scrbase}} \Macro{defcaptionname} command always
defines the \PName{term}, thus overwriting any previous definition. As with
\Macro{providecaptionname}, the language specified need not be previously
defined.
\KOMAScript{} itself uses \Macro{providecaptionname} to define the commands in
\autoref{sec:scrlttr2-experts.languages}.
\DescPageRef{scrlttr2-experts.cmd.yourrefname}.
\begin{Example}
If you prefer ``fig.'' instead of ``figure'' in \PValue{USenglish}, you can
achieve this using:
\begin{lstcode}
\renewcaptionname{USenglish}{\figurename}{fig.}
\end{lstcode}
If you want the same change not only in \PValue{USenglish} but also in
\PValue{UKenglish}, you do not need an additional:
\begin{lstcode}
\renewcaptionname{UKenglish}{\figurename}{fig.}
\end{lstcode}
but can simply extend the \PName{language list}:
\begin{lstcode}
\renewcaptionname{USenglish,UKenglish}{\figurename}{fig.}
\end{lstcode}
You can extend the \PName{language list} in the same manner with
\PValue{american}, \PValue{australian}, \PValue{british}, \PValue{canadian},
and \PValue{newzealand}.
\end{Example}
Since \KOMAScript~3.12\ChangedAt{v3.12}{\Package{scrbase}}, you no longer need
to delay the definition or redefinition until
\Macro{begin}\PParameter{document} using \Macro{AtBeginDocument} because
\Package{scrbase} does this itself if the commands are called in the
document's preamble. Additionally, \Package{scrbase} now checks if a term
should be redefined in \Macro{extras\PName{language}} instead of
\Macro{captions\PName{language}}. The new starred variants of the commands
always use \Macro{extras\PName{language}}. So redefining language-dependent
terms for packages like \Package{hyperref} that use
\Macro{extras\PName{language}} should work as expected.
Language-dependent terms that are commonly defined by classes and language
packages are described in \autoref{tab:scrbase.commonNames}.
\begin{desclist}
\renewcommand*{\abovecaptionskipcorrection}{-\normalbaselineskip}%
\desccaption[{%
Overview of common language-dependent terms%
}]{%
Overview of language-dependent terms of typical language packages%
\label{tab:scrbase.commonNames}%
}{%
Overview of common language dependent terms
(\emph{continued})%
}%
\entry{\Macro{abstractname}}{%
heading of the abstract%
\IndexCmd{abstractname}%
}%
\entry{\Macro{alsoname}}{%
``see also'' in additional cross references of the index%
\IndexCmd{alsoname}%
}%
\entry{\Macro{appendixname}}{%
``appendix'' in the heading of an appendix chapter%
\IndexCmd{appendixname}%
}%
\entry{\Macro{bibname}}{%
heading of the bibliography%
\IndexCmd{bibname}%
}%
\entry{\Macro{ccname}}{%
prefix heading for the distribution list of a letter%
\IndexCmd{ccname}%
}%
\entry{\Macro{chaptername}}{%
``chapter'' in the heading of a chapter%
\IndexCmd{chaptername}%
}%
\entry{\Macro{contentsname}}{%
heading of the table of contents%
\IndexCmd{contentsname}%
}%
\entry{\Macro{enclname}}{%
prefix heading for the enclosures of a letter%
\IndexCmd{enclname}%
}%
\entry{\Macro{figurename}}{%
prefix heading of figure captions%
\IndexCmd{figurename}%
}%
\entry{\Macro{glossaryname}}{%
heading of the glossary%
\IndexCmd{glossaryname}%
}%
\entry{\Macro{headtoname}}{%
``to'' in header of letter pages%
\IndexCmd{headtoname}%
}%
\entry{\Macro{indexname}}{%
heading of the index%
\IndexCmd{indexname}%
}%
\entry{\Macro{listfigurename}}{%
heading of the list of figures%
\IndexCmd{listfigurename}%
}%
\entry{\Macro{listtablename}}{%
heading of the list of tables%
\IndexCmd{listtablename}%
}%
\entry{\Macro{pagename}}{%
``page'' in the pagination of letters%
\IndexCmd{pagename}%
}%
\entry{\Macro{partname}}{%
``part'' in the heading of a part%
\IndexCmd{partname}%
}%
\entry{\Macro{prefacename}}{%
heading of the preface%
\IndexCmd{prefacename}%
}%
\entry{\Macro{proofname}}{%
prefix heading of mathematical proofs%
\IndexCmd{proofname}%
}%
\entry{\Macro{refname}}{%
heading of the list of references%
\IndexCmd{refname}%
}%
\entry{\Macro{seename}}{%
``see'' in cross references of the index%
\IndexCmd{seename}%
}%
\entry{\Macro{tablename}}{%
prefix heading at table captions%
\IndexCmd{tablename}%
}%
\end{desclist}
%
\EndIndexGroup
%
\EndIndexGroup
\section{Identifying \KOMAScript}
\seclabel{identify}
Although\,---\,or especially because\,---\,\Package{scrbase} is generally
designed as a package for authors of classes and packages, it is of course
used by the \KOMAScript{} classes and most \KOMAScript{} packages. It
therefore contains two commands that are present in all \KOMAScript{} classes
and all basic \KOMAScript{} packages.
\begin{Declaration}
\Macro{KOMAScript}
\end{Declaration}
This command simply sets the word ``\KOMAScript'' in sans-serif font and with
a slight tracking for the capitals. By the way, all \KOMAScript{} classes and
packages define this command as required. The definition is robust using
\Macro{DeclareRobustCommand}. Since packages that do not belong to
\KOMAScript{} can also define this command, its existence should not be
interpreted as an indication that a \KOMAScript{} package is in use.%
\EndIndexGroup
\begin{Declaration}
\Macro{KOMAScriptVersion}
\end{Declaration}
\KOMAScript{} defines the major version of \KOMAScript{} in this command. It
has the form ``\PName{date} \PName{version} \texttt{KOMA-Script}''. This major
version is same for all \KOMAScript{} classes and all \KOMAScript{} packages
used by the classes. For this reason, it can be queried after you
load \Package{scrbase}, too. For example, this guide was made using
\KOMAScript{} version ``\KOMAScriptVersion''.
%
\EndIndexGroup
\section{Extensions to the \LaTeX{} Kernel}
\seclabel{latexkernel}
Sometimes the \LaTeX{} kernel itself provides commands but lacks other very
similar commands that would often be useful. A few such commands are provided
by \Package{scrbase} for authors of packages and classes.
\begin{Declaration}
\Macro{ClassInfoNoLine}\Parameter{class name}\Parameter{information}%
\Macro{PackageInfoNoLine}\Parameter{package name}\Parameter{information}%
\end{Declaration}%
The \LaTeX{} kernel already provides authors of classes and packages commands
like \Macro{ClassInfo} and \Macro{PackageInfo} to write information, along
with the current line number, to the log file. In addition to
\Macro{PackageWarning} and \Macro{ClassWarning}, which throw warning messages
with line numbers, it also provides \Macro{PackageWarningNoLine} and
\Macro{ClassWarningNoLine} for warning messages without line numbers. However
the obvious commands \Macro{ClassInfoNoLine} and \Macro{PackageInfoNoLine},
for writing information without line numbers into the log file, are missing.
The \Package{scrbase} package provides them.
%
\EndIndexGroup
\begin{Declaration}
\Macro{l@addto@macro}\Parameter{command}\Parameter{extension}%
\end{Declaration}%
The \LaTeX{} kernel provides an internal command \Macro{g@addto@macro} to
extend the definition of macro \Macro{command} globally with
\PName{extension}. This works in this form only for macros that have no
arguments. However, sometimes you may need a command like this that works
locally within the current group. The \Package{scrbase} package provides such
a command with \Macro{l@addto@macro}. An alternative is to use the
\Package{etoolbox}\IndexPackage{etoolbox} or
\Package{xpatch}\IndexPackage{xpatch} package, which offers a whole range of
such commands for different purposes (see \cite{package:etoolbox} or
\cite{package:xpatch}).%
\EndIndexGroup
\section{Extensions to the Mathematical Features of \eTeX}
\seclabel{etex}
\eTeX{}, which is used by \LaTeX{} and loaded by \KOMAScript{}, has extended
capabilities for calculating simple arithmetic with \TeX{} counters and
integers using \Macro{numexpr}\IndexCmd{numexpr}. The four basic arithmetic
operations and parentheses are supported. Division is rounded
correctly. Sometimes additional operators would be useful.
\begin{Declaration}
\Macro{XdivY}\Parameter{dividend}\Parameter{divisor}%
\Macro{XmodY}\Parameter{dividend}\Parameter{divisor}%
\end{Declaration}%
The\ChangedAt{v3.05a}{\Package{scrbase}} \Macro{XdivY} command returns the
value of the integer quotient, with the \Macro{XmodY} command giving the value
of the remainder. This type of of division is defined by the equation
\[
\textit{dividend} = \textit{divisor} \cdot
\textit{integer quotient} + \textit{remainder}
\]
where \textit{dividend}, \textit{divisor}, and \textit{remainder} are
integers, \textit{remainder} is greater or equal to 0 and less than
\textit{divisor}, and \textit{divisor} is a natural number greater than 0.
You can assign the value to a counter or use it directly within an expression
using \Macro{numexpr}. To output the value as an Arabic number, you must
prefix it with \Macro{the}.%
%
\EndIndexGroup
\section[{General Mechanism for Multi-Level Hooks}]
{General Mechanism for Multi-Level
Hooks\ChangedAt[2019/01]{v3.27}{\Package{scrbase}}}
\seclabel{hooks}
\BeginIndexGroup
\BeginIndex{}{Hooks}
The \LaTeX{} kernel provides a few \emph{hooks} in the processing of
a document where additional code can be inserted. Class and package authors
should be very familiar with \Macro{AtBeginDocument} and
\Macro{AtEndDocument}. \KOMAScript{} offers similar features in some places,
for example to hook code into the execution of
\hyperref[sec:maincls.structure]{sectioning commands}. Over the years, there
have been two problems:
\begin{itemize}
\item There are never enough hooks.
\item There is some code that should only be executed once, as if it almost
drops off the hook, as well as code that must be executed each time the
hook is encountered, thus remaining permanently on the hook.
\end{itemize}
Usually, to define a single hook you must define a command that collects the
code for each hook. This code is then stored in another internal macro, which
must be inserted at the point where the collected code is executed. The more
hooks you insert, the more such commands there are. To allow for both
single-use code and permanent code may even require two hooks, and therefore
twice the number of commands to be defined.
The example of sectioning commands shows that the first problem can sometimes
be exacerbated by having only a single point for code execution. One package
author may need only one way to execute the same code for all sectioning
commands. Another package author would prefer to execute different code for
certain sectioning commands only. Meeting both these demands would require a
general hook as well as a hook for each sectioning command. These requirements
are doubled again because of the second problem.
\KOMAScript{} therefore offers a generalized hook mechanism in
\Package{scrbase} that provides multi-level hooks for both single-use and
persistent code. These hooks are named \emph{do-hooks} because of their
implementation. From this also comes the names of the instructions by which
they are controlled.
\begin{Declaration}
\Macro{ExecuteDoHook}\Parameter{specifier}
\end{Declaration}
Hooks\ChangedAt[2019/01]{v3.27}{\Package{scrbase}} are implemented with this
command. The \PName{specifier} determines the name or names of the hook. The
\PName{specifier} is always completely expanded for analysis.
The \PName{specifier} generally consists of strings separated by forward
slashes (``/''). Initially, \Macro{ExecuteDoHook} divides the string at the
first slash. The first part is the name. The remainder (without the slash) is
the argument. Then the code for the hook with this name is executed. Next the
first part of the remaining string is divided again from the remainder,
combined with a slash after the name to form a new name, and the code with
this name is executed. This process continues until the code for the hook with
the name \PName{specifier} has been executed and the argument is empty.
In the simplest case, the \PName{specifier} consists of a single name. In this
case, the persistent code is executed first, with an empty argument, for
exactly one hook specified by this name.
At each stage of execution, single-use code is also executed after the hook's
persistent code, and then the single-use code is globally removed from the
hook.
\begin{Example}
By inserting \DescRef{\LabelBase.cmd.ExecuteDoHook}%
\PParameter{heading/begingroup/\PName{name}} into the execution of each
sectioning command defined with
\DescRef{maincls-experts.cmd.DeclareSectionCommand}, the \KOMAScript{}
classes ultimately have six hooks inserted at that code-point, executed in
this order:
\begin{enumerate}
\item \PValue{heading} with the argument \PValue{begingroup/}\PName{name}
for persistent code,
\item \PValue{heading} with the argument \PValue{begingroup/}\PName{name}
for single-use code,
\item \PValue{heading/begingroup} with the argument \PName{name} for
persistent code,
\item \PValue{heading/begingroup} with the argument \PName{name} for
single-use code,
\item \PValue{heading/begingroup/}\PName{name} with an empty argument for
persistent code,
\item \PValue{heading/begingroup/}\PName{name} with an empty argument for
single-use code.
\end{enumerate}
The \PName{name} is the name of section level specified in
\DescRef{maincls-experts.cmd.DeclareSectionCommand},
\DescRef{maincls-experts.cmd.DeclareNewSectionCommand} or
\DescRef{maincls-experts.cmd.ProvideSectionCommand}, or the sectioning
command specified by it, for example \PValue{chapter} or
\PValue{subparagraph}. Looking at the list above, and considering that there
are various sectioning commands, it becomes clear that the \PValue{heading}
and \PValue{heading/begingroup} hooks will be called multiple times for each
sectioning command.%
\end{Example}%
%
\EndIndexGroup
\begin{Declaration}
\Macro{AddtoDoHook}\Parameter{name}\Parameter{command}
\Macro{AddtoOneTimeDoHook}\Parameter{name}\Parameter{command}
\end{Declaration}
\Macro{AddtoDoHook}\ChangedAt[2019/01]{v3.27}{\Package{scrbase}} appends
persistent code to the hook named \PName{name}. The code to be added is the
\PName{command}, to which the argument mentioned in the description of
\DescRef{\LabelBase.cmd.ExecuteDoHook} is appended as a parameter.
\begin{Example}
Suppose you want to count how many times the \Macro{section} command is
executed. This would be simple, continuing the previous example:
\begin{lstcode}
\newcounter{sectionCounter}
\AddtoDoHook{heading/begingroup/section}
{\stepcounter{sectionCounter}}
\end{lstcode}
However, in reality, \Macro{stepcounter}\PParameter{sectionCounter}%
\PParameter{} would be executed. Remember that an argument is always appended
as a parameter. In the case of the hook named
\PValue{heading/begingroup/section}, this argument is empty. Since an empty
parameter becomes an empty group here, it is better to consume this empty
parameter:
\begin{lstcode}
\newcommand*{\stepcountergobble}[2]{%
\stepcounter{#1}%
}
\AddtoDoHook{heading/begingroup/section}
{\stepcountergobble{sectionCounter}}
\end{lstcode}
Here, the appended, empty parameter of \Macro{stepcountergobble} is read but
not used.
If instead of \Macro{section}, you want to count all sectioning commands, you
only need to change the hook name:
\begin{lstcode}
\AddtoDoHook{heading/begingroup}
{\stepcountergobble{sectionCounter}}
\end{lstcode}
By the way, the appended parameter is not empty in this case but contains the
name of the sectioning level or sectioning command. If you wanted to count
the sectioning commands individually, you could just use this:
\begin{lstcode}
\newcommand*{\stepCounter}[1]{%
\stepcounter{#1Counter}%
}
\AddtoDoHook{heading/begingroup}
{\stepCounter}
\end{lstcode}
Of course, you must also define the counters \Counter{partCounter},
\Counter{chapterCounter} down to \Counter{subparagraphCounter}.
\end{Example}
The \Macro{AddtoOneTimeDoHook} command works similarly but adds the
\PName{command} to the single-use code. This code will be globally removed
after the first execution.%
\EndIndexGroup
\begin{Declaration}
\Macro{ForDoHook}\Parameter{specification}\Parameter{command}
\end{Declaration}
While\ChangedAt[2019/01]{v3.27}{\Package{scrbase}}
\DescRef{\LabelBase.cmd.ExecuteDoHook} executes the commands previously stored
with \DescRef{\LabelBase.cmd.AddtoDoHook} or
\DescRef{\LabelBase.cmd.AddtoOneTimeDoHook} for the hook given by the
\PName{specifier}, this macro executes the \PName{command} immediately. There
are two parameters added to the \PName{command}. The first is the hook's name;
the second, the hook's argument.
This command is a byproduct of the implementation of
\DescRef{\LabelBase.cmd.ExecuteDoHook}. Normally, neither end users nor package
authors should need this command.%
\EndIndexGroup
\begin{Declaration}
\Macro{SplitDoHook}\Parameter{specifier}\Parameter{head macro}
\Parameter{remainder macro}
\end{Declaration}
As\ChangedAt[2019/01]{v3.27}{\Package{scrbase}} can be seen from the preceding
explanations, the parameter of a \PName{command} added with
\DescRef{\LabelBase.cmd.AddtoDoHook} or
\DescRef{\LabelBase.cmd.AddtoOneTimeDoHook} can also be a multi-part
\PName{specifier}. You can use \Macro{SplitDoHook} to divide a
\PName{specifier} into the front element and the remainder. The
\PName{head macro} will be set to the front element. The \PName{remainder
macro} will be set to the rest. If there is no remainder left, the
\PName{remainder macro} is set to empty. If the \PName{specifier} was already
empty, a warning is issued and both the \PName{head macro} and the
\PName{remainder macro} are set to empty.
\begin{Example}
If you want to increase a counter at the start of a group in which a heading
is issued but decrease it at the end, you can do this with two hooks:
\begin{lstcode}
\AddtoDoHook{heading/begingroup}
{\stepCounter}
\newcommand*{\restepCounter}[1]{%
\addtocounter{#1Counter}{-1}%
}
\AddtoDoHook{heading/endgroup}
{\restepCounter}
\end{lstcode}
But you could also use a single hook and split its parameters:
\begin{lstcode}
\newcommand*{\changeCounter}[1]{%
\SplitDoHook{#1}{\Group}{\Level}%
\Ifstr{\Group}{begingroup}{%
\stepcounter{\Level Counter}%
}{%
\Ifstr{\Group}{endgroup}{%
\addtocounter{\Level Counter}{-1}%
}{}%
}%
}
\AddtoDoHook{heading}
{\changeCounter}
\end{lstcode}
As you can see, the first solution is much simpler. In addition, it would
be easy to overlook including the empty group for the second false-case in
the second example. That would be fatal, however, as there make be other
hooks with named \PValue{heading} but with different arguments.
\end{Example}
Strictly speaking, this command is a byproduct of the implementation of
\DescRef{\LabelBase.cmd.ForDoHook}.%
\EndIndexGroup
%
\EndIndexGroup
\section{Obsolete Options and Commands}
\seclabel{obsolete}
% TODO: Fix new translation
Prior release of \Package{scrbase} provided some options and commands that has
been removed or replaced meanwhile. Those are documented in this section only
for completeness but shouldn't be used any longer.
% :ODOT
% \LoadNonFree{scrbase}{0}% not available in English
\begin{Explain}
\begin{Declaration}
\Macro{FamilyElseValues}
\end{Declaration}
Since version 3.12 the command is deprecated. Nevertheless,
\Package{scrbase} detects its use and issues a message requesting that you
update the code accordingly.%
\EndIndexGroup%
\begin{Declaration}
\OptionVName{internalonly}{value}
\end{Declaration}
Since version 3.28 this option is deprecated. For compatibility it is
processed (see \DescRef{\LabelBase.cmd.FamilyKeyStateProcessed}) but
ignored.%
\EndIndexGroup%
\end{Explain}%
%
\EndIndexGroup
\endinput
%%% Local Variables:
%%% mode: latex
%%% mode: flyspell
%%% ispell-local-dictionary: "en_GB"
%%% coding: utf-8
%%% TeX-master: "../guide.tex"
%%% End:
|