summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/doc/latex/keyreader/keyreader-guide.tex
blob: 214e129f09f1039ee15def593f8caf38972fbc17 (plain)
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
\documentclass{article}
\usepackage[scaled=0.9]{helvet}
\usepackage{lipsum,parskip,xspace}
\usepackage{fancyvrb}
\usepackage{xcolor}
\usepackage{multicol}
\usepackage{hyperref}
\usepackage[parser=;,macroprefix=mp@,keyprefix=KV,
  keyfamily=fam]{keyreader}
\makeatletter
\newcommand*\email[1]{\href{mailto:#1}{#1}}
\skip\footins20pt\relax
\xglobal\definecolorset{rgb}{x}{1}{green,0.00,0.59,0.00;%
  brown,0.50,0.00,0.50;teal,0.00,0.82,0.82;%
  magenta,0.50,0.00,1.00;purple,0.50,0.00,0.25}
\colorlet{verbcolor}{blue}
\def\eg{\KR@ifnextchar.{e.g}{e.g.}\xspace}
\def\ie{\KR@ifnextchar.{i.e}{i.e.}\xspace}
\def\etc{\KR@ifnextchar.{etc}{etc.}\xspace}
\def\bparen{\textup{(}\unskip}
\def\eparen{\unskip\textup{)}\xspace}
\def\krvert{$\vert$}
\date{\textcolor{blue}{\small\today}}
\hypersetup{colorlinks=true,linkcolor=red,pdfpagemode=UseThumbs,
  implicit=true,breaklinks=true,pagebackref=true,backref=true,
  bookmarks=true,bookmarksnumbered=true,hyperfootnotes=true,debug=true,
  naturalnames=false,citecolor=purple,pdfview=FitH,pdfstartview=FitH}
\def\krverblabel{%
  \textcolor{green}{\fboxrule1pt\fcolorbox{red}{gray!45}{\hspace{1cm}}}}
\CustomVerbatimEnvironment{krverbatim}{Verbatim}{numbers=left,
  label={\krverblabel},labelposition=topline,numberblanklines=false, firstnumber=last,frame=single,rulecolor=\color{xmagenta1},framerule=1pt,
  framesep=7pt,formatcom=\color{verbcolor},xrightmargin=0pc,
  commandchars=\|\(\),commentchar=&}
\renewcommand\theenumi{\alph{enumi}}
\renewcommand\labelenumi{\theenumi\textup{)}}
\renewcommand\theenumii{\roman{enumii}}
\renewcommand\labelenumii{\theenumii\textup{)}}
\renewcommand\p@enumii{\theenumi--}
\newcommand*\sty[1]{\KR@cs{#1}{xgreen1}}
\newcommand*\cs[1]{\KR@cs{#1}{xbrown1}}
\newcommand*\cx[1]{\KR@cx{#1}{xbrown1}}

\begin{document}
\DefineShortVerb{\+}
\title{The \texttt{\color{blue}keyreader} Package\footnote{\color{red}Version 0.3.}}
\author{Ahmed Musa\\\email{a.musa@rocketmail.com}}
\maketitle
\thispagestyle{empty}

\leavevmode\textcolor{blue}{\rule[0ex]{\hsize}{2pt}}
\columnseprule0.5pt\premulticols2cm\relax
\begin{multicols}{2}
  \small\tableofcontents\normalsize
\end{multicols}
\removelastskip
\leavevmode\textcolor{blue}{\rule[0ex]{\hsize}{2pt}}

\section{Motivation}

Toggle switches or booleans were introduced by the \sty{etoolbox} package and have proved very useful mainly for two reasons: unlike the legacy \TeX{} switches which require three commands per switch, toggles require only one command per switch, and toggles occupy their own separate name space, thereby avoiding clashes with other macros. So we can effectively have both the following sets in the same file:
\begin{krverbatim}
\newif\ifmyboolean    ->  3 separate commands:
                          \if<myboolean> <myboolean>true
                          <myboolean>false

\newtoggle{myboolean} ->  only 1 command and no clash with
                          commands in other name spaces.
\end{krverbatim}

However, the \sty{xkeyval} package can't be used to define and set toggle keys. The present package fills this gap, by providing facilities for defining and setting toggle keys. The work relies on some of the macros from the \sty{xkeyval} package.

Secondly, the \sty{xkeyval} package can't be used to define and set complementary keys, which can be handy in the case of boolean keys. The present package introduces this concept and additionally permits the submission of individual/different custom key macros to the complementary keys.

The third motivation for this package relates to economy of tokens in style files. The \sty{xkeyval} package provides \cs{\define@cmdkeys} and \cs{\define@boolkeys} for defining and setting multiple command keys and boolean keys, but in each category the keys must have the same default value and no key macro/function. This package seeks to remove these restrictions, so that multiple keys of all categories (ordinary keys, command keys, boolean keys, tog keys, and choice keys) can be defined in one go (using only one command) and those keys can have different default values and functions. This greatly minimizes tokens, as hundreds of keys can, in principle, be issued simultaneously by one command.

\section{Package loading}

The package can be loaded in style and class files by
\begin{krverbatim}
\RequirePackage[options]{keyreader}
\end{krverbatim}
and in document files via
\begin{krverbatim}
\usepackage[options]{keyreader}
\end{krverbatim}
where the options and their default values are
\begin{krverbatim}
parser=;, macroprefix=mp@, keyprefix=KV, keyfamily=fam,
xchoicelist=false.
\end{krverbatim}
The \cs{parser} is the separator between the keys in the key list to be defined in one go (see examples in section~\ref{sec:examples}). All these options can be set dynamically by using the \cs{\krsetup} macro:
\begin{krverbatim}
\krsetup{parser=;, macroprefix=mp@, keyprefix=KV,
  keyfamily=fam, xchoicelist=false}.
\end{krverbatim}

\section{Complementary boolean keys}

The syntax of complementary boolean keys is
\begin{krverbatim}
\define@comp@boolkeys[<key-prefix>]{<family>}[<macro-prefix]
  {<primary boolean>}[<default value for primary boolean>]
  {<secondary boolean>}{<func for primary boolean>}
  {<func for secondary boolean>}.
\end{krverbatim}

When the user doesn't supply the \cs{<key-prefix>} and/or \cs{<macro-prefix>}, the package will use \cs{<KV>} and \cs{<mp@>}, respectively. When one boolean (primary or secondary) is true, the other is automatically set false. Infinite loops, which are possible in back-linked key settings, are avoided in the \sty{keyreader} package.

As an example, we define below two complementary keys \cs{<draft>} and \cs{<final>} with different key macros:
\begin{krverbatim}
\define@comp@boolkeys[KV]{fam}[mp@]{draft}[true]{final}%
  {%
    \def\gobble##1{}%
  }{%
    \def\notgobble##1{##1}%
  }.
\end{krverbatim}
The key prefix (default \cs{<KV>}), macro prefix (default \cs{<mp@>}), and key macros (no default) can be empty:
\begin{krverbatim}
\define@comp@boolkeys{fam}{draft}[true]{final}{}{}.
\end{krverbatim}

The defined complementary keys \cs{<draft>} and \cs{<final>} can now be set as follows:
\begin{krverbatim}
\setkeys[KV]{fam}{draft=true}

\setkeys[KV]{fam}{final=true}
\end{krverbatim}
The second statement above reverses the boolean \cs{<draft>} to \cs{<false>}, which had been set in the first statement to \cs{<true>}. There is no meaning to the following:
\begin{krverbatim}
\setkeys[KV]{fam}{draft=true,final=true}.
\end{krverbatim}

Most applications of the \sty{xkeyval} package do indeed use key and macro prefixes; so it presumably makes sense here to assume that all uses of the present package will involve key and macro prefixes.

\section{Toggle switches and keys}
\label{sec:toggles}

\subsection{Toggle switches}

The following toggle switches are defined in the \sty{keyreader} package. They largely mimic those in the \sty{etoolbox} package, except for the commands \cs{\deftog} and \cs{\requiretog}. There is no fear that the commands in this package will interfere with those from the \sty{etoolbox} package, since the control sequence names are different.

\medskip
\begin{krverbatim}
\deftog{<toggle>}
\end{krverbatim}
This defines a new \cs{<toggle>} whether or not \cs{<toggle>} is already defined. If \cs{<toggle>} is already defined, a warning message is logged in the transcript file and the new definition is effected.

\medskip
\begin{krverbatim}
\newtog{<toggle>}
\end{krverbatim}
This defines a new \cs{<toggle>} if \cs{<toggle>} is not already defined; otherwise the package issues a fatal error.

\medskip
\begin{krverbatim}
\providetog{<toggle>}
\end{krverbatim}
This defines a new \cs{<toggle>} if \cs{<toggle>} is not already defined. If \cs{<toggle>} is already defined, the command does nothing.

\medskip
\begin{krverbatim}
\requiretog{<toggle>}
\end{krverbatim}

\cs{\requiretog} takes arguments like \cs{\newtog} and behaves like \cs{\providetog} with the difference: if the toggle is already defined, the command \cs{\requiretog} calls \LaTeX's \cs{\CheckCommand} to make sure that the new and existing definitions are identical, whereas \cs{\providetog} assumes that if the toggle is already defined, the existing definition should persist. \cs{\requiretog} assures that a toggle will have the given definition, but \cs{\requiretog} also warns the user if there was a previous and different existing definition. For example, if the toggle \cs{<toga>} is currently \cs{<true>}, then since all new toggles start out as \cs{<false>}, a call \cx{\requiretog{toga}} will issue a warning in the log file that the new and old definitions of \cs{<toga>} don't agree and the new definition, therefore, can't go ahead.

The \sty{keyreader} package also provides the command \cs{\requirecmd}, which has the same logic as \cs{\requiretog} but can be used for general \LaTeX{} commands, including those with optional arguments.

\medskip
\begin{krverbatim}
\settog{<toggle>}{<true |krvert false>}
\end{krverbatim}
This command sets \cs{<toggle>} to \cs{<value>}, where \cs{<value>} may be either \cs{<true>} or \cs{<false>}. This statement will issue an error if \cs{<toggle>} wasn't previously defined.

\medskip
\begin{krverbatim}
\togtrue{<toggle>}
\end{krverbatim}
This sets \cs{<toggle>} to \cs{<true>}. It will issue an error if \cs{<toggle>} wasn't previously defined.

\medskip
\begin{krverbatim}
\togfalse{<toggle>}
\end{krverbatim}
This sets \cs{<toggle>} to \cs{<false>}. It will issue an error if \cs{<toggle>} wasn't previously defined.

\medskip
\begin{krverbatim}
\iftog{<toggle>}{<true>}{<false>}
\end{krverbatim}
This yields the \cs{<true>} statement if the boolean \cs{<toggle>} is currently \cs{<true>}, and \cs{<false>} otherwise. It will issue an error if \cs{<toggle>} wasn't previously defined.

\medskip
\begin{krverbatim}
\ifnottog{<toggle>}{<not true>}{<not false>}
\end{krverbatim}
This behaves like \cs{\iftog} but the logic of the test is reversed. It will issue an error if \cs{<toggle>} wasn't previously defined.

\subsection{Toggle keys}

The syntax for defining toggle keys is exactly like those for boolean keys in the \sty{xkeyval} package:
\begin{krverbatim}
\define@togkey[<pre>]{<fam>}[<mp>]{<key>}[<default>]{<func>}
\define@togkey+[<pre>]{<fam>}[<mp>]{<key>}[<default>]%
  {<func1>}{<func2>}
\end{krverbatim}

If the macro prefix \cs{<mp>} is not specified, these create a toggle of the form \cs{<pre>@<family>@<key>} using \cs{\newtog} (which initializes the switch to \cs{<false>}) and a key macro of the form \cs{\<pre>@<family>@<key>} which first checks the validity of the user input. If the value is valid, it uses it to set the boolean and then executes \cs{<func>}. If the user input wasn't valid, then the boolean will not be set and the package will generate a fatal error.

If \cs{<mp>} is specified, then the key definition process will create a toggle of the form \cs{<mp><key>} and a key macro of the form \cs{\<pre>@<family>@<key>}. The value \cs{<default>} will be used by the key macro when the user sets the key without a value.

If the \cs{+} version of the macro is used, the user can specify two key macros \cs{<func1>} and \cs{<func2>}.

If user input is valid, the macro will set the toggle and executes \cs{<func1>}; otherwise, it will not set the boolean but will execute \cs{<func2>}.

As an example, consider the following (adapted from the \sty{xkeyval} package to suit toggle keys):

\begin{krverbatim}
\define@togkey{fam}[my@]{frame}{%
  \iftog{my@frame}{%
    \PackageInfo{mypack}{Turning frames on}%
  }{%
    \PackageInfo{mypack}{Turning frames off}%
  }%
}

\define@togkey+{fam}{shadow}{%
  \iftog{KV@fam@shadow}{%
    \PackageInfo{mypack}{Turning shadows on}%
  }{%
    \PackageInfo{mypack}{Turning shadows off}%
  }%
}{%
    \PackageWarning{mypack}{Erroneous input `#1' ignored}%
}
\end{krverbatim}

The first example creates the toggle \cs{<my@frame>} and defines the key macro
\cs{\KV@fam@frame} to set the boolean (if the input is valid). The second key intimates
the user of changed settings, or produces a warning when input was incorrect.

It is also possible to define multiple toggle keys with a single command
\begin{krverbatim}
\define@togkeys[<pre>]{<fam>}[<mp>]{<keys>}[<default>]
\end{krverbatim}
This creates a toggle key for every entry in the comma-separated list \cs{<keys>}. As is the case with the commands \cs{\define@cmdkeys} and \cs{\define@boolkeys} from the \sty{xkeyval} package, the individual keys in this case can't have a custom function. See section~\ref{sec:multiplekeys} for how to define multiple keys with custom functions.

As an example of defining multiple toggle keys, consider
\begin{krverbatim}
\define@togkeys{fam}[my@]{toga,togb,togc}
\end{krverbatim}

This is an abbreviation for
\begin{krverbatim}
\define@togkey{fam}[my@]{toga}{}
\define@togkey{fam}[my@]{togb}{}
\define@togkey{fam}[my@]{togc}{}
\end{krverbatim}

Now we can do
\begin{krverbatim}
\define@togkey{fam}[my@]{book}{%
  \iftog{my@book}{\krsetkeys[KV]{fam}{togc=true}}{}%
}

\krsetkeys[KV]{fam}{book=true}
\end{krverbatim}

Toggle keys can be set in the same way that other key types are set. \cs{\krsetkeys} is introduced by the \sty{keyreader} package as a drop-in replacement for the legacy \cs{\setkeys} of the \sty{xkeyval} package (see Section~\ref{sec:dirty-trick}). \cs{\setkeys} can still be used when the situation permits (see Section~\ref{sec:dirty-trick}).

The status of toggles can be examined by doing
\begin{krverbatim}
\show\<KR@toggle@><mp><key>
\end{krverbatim}
when the \cs{<mp>} is present. When the user has specified no \cs{<mp>} in defining the key, he has to issue
\begin{krverbatim}
\show\<KR@toggle@><pre>@<family>@<key>.
\end{krverbatim}

\section{Defining multiple keys by one command}
\label{sec:multiplekeys}

The main user interface for defining multiple keys is the \cs{\define@keylist} macro, whose syntax is
\begin{krverbatim}
\define@keylist{<key type/id>, <key>, <key default value>,
  <key macro/function>; <another set of key specifiers>; etc}
\end{krverbatim}

There are five key types: 1 (ordinary key), 2 (command key), 3 (boolean key),
4 (toggle key), and 5 (choice key). The key and its attributes are separated by commas; they constitute one \cs{object}. The objects are separated by the \cs{<parser>}, which is the semicolon in the above example.

If the key list is available in a macro, say,
\begin{krverbatim}
\def\keylist{<key type/id>, <key>, <key default value>,
  <key macro/function>; <another set of key specifiers>; etc},
\end{krverbatim}
then the keys can be defined by the starred form of \cs{\define@keylist}:
\begin{krverbatim}
\define@keylist*\keylist.
\end{krverbatim}
\cx{\define@keylist*} takes a macro as argument, while \cs{\define@keylist} accepts a key list.

\subsection{Choice key values}

The \cs{\ChoiceKeyValues} macro is needed for choice keys; it lists the alternate
admissible values for a choice key and thus can't be empty when a choice key
is being defined. Its syntax is
\begin{krverbatim}
\ChoiceKeyValues{<key>}{<comma-separated list of admissible
   key values>}.
\end{krverbatim}
To further save tokens, the macro \cs{\ChoiceKeyValues} may be abbreviated by \cs{\CKVS}. It has to be defined each time a choice key is being defined. For example, if we want to define two choice keys \cs{align} and \cs{election}, then before the call to \cs{\define@keylist}, we have to set
\begin{krverbatim}
\CKVS{align}{center,right,left,justified}
\CKVS{election}{state,federal,congress,senate}.
\end{krverbatim}
It doesn't matter which choice key first gets a \cs{\CKVS}. The prevailing key family, obtainable from \cs{\KR@keyfamily}, is used internally by \cs{\ChoiceKeyValues} to build distinct alternate values lists for choice keys. \emph{Unless the key family changes, you can't set two \cs{\ChoiceKeyValues} for the same choice key. This will be possible only if the package option \cs{xchoicelist} \bparen meaning ``allow overwriting of choice list''\eparen has been set \cs{<true>}, either through \cs{\documentclass}, \cs{\usepackage}, or \cs{\krsetup}}. Thus any number of choice keys can appear in one \cs{\define@keylist} or \cx{\define@keylist*} statement if their lists of alternate/admissible values have been set by \cs{\CKVS}.

As mentioned earlier, the key family and other package options can be changed dynamically via
\begin{krverbatim}
\krsetup{parser=value,macroprefix=value,keyprefix=value,
  keyfamily=value,xchoicelist=value}.
\end{krverbatim}

In line with the philosophy of the \sty{xkeyval} package, all the choice keys to be defined using the \sty{keyreader} package require \cs{\ChoiceKeyValues}: choice keys, by definition, have pre-ordained or acceptable values.

\subsection{Internals}

The internal equivalent of \cs{\ChoiceKeyValues} (the choice key list of alternative values) is the macro \cs{\<family@key@altlist>}. For example, for the \cs{align} key above, the internal of \cs{\CKVS} is \cs{\fam@align@altlist}, assuming the current family is \cs{fam}.

For all keys in a family, the internal of the key macro/function is available in  \cs{\<family@key@func>}, and the value submitted by the user when setting the key can be accessed via the macro \cs{\<family@key@value>}.

\subsection{Examples}
\label{sec:examples}

Suppose that the key family and other attributes have been set as
\begin{krverbatim}
\krsetup{parser=;,macroprefix=mp@,keyprefix=KV,
  keyfamily=fam,xchoicelist=false}.
\end{krverbatim}
Further, suppose we wish to define a set of keys \cs{<color,angle,scale,align>}. The keys \cs{color}, \cs{angle} and \cs{scale} will de defined using command keys, while the key \cs{align} will be defined by choice keys. Assume that the \cs{align} key can only assume the values \cs{<center,right,left,justified>}, where the first three values would further imply \cs{\centering}, \cs{\flushright}, and \cs{\flushleft}, respectively. Moreover, we assume that the key \cs{scale} will be associated with a macro called \cs{\mydo}, where \cs{\do} is assumed defined elsewhere. The keys \cs{color} and \cs{angle} aren't associated with macros. Then we can go:
\begin{krverbatim}
\CKVS{align}{center,right,left,justified}
\CKVS{weather}{sunny,cloudy,lightrain,heavyrain,snow,
  sleet,windy,\someweather}
  % |color(gray) We assume that \someweather is defined
  % |color(gray) somewhere and holds an admissible value
  % |color(gray) for the key ``weather'' at any level.|color(verbcolor)
\def\f@align{%
  \ifcase\nr\relax
    \def\mp@align{\centering}%
  \or
    \def\mp@align{\flushright}%
  \or
    \def\mp@align{\flushleft}%
  \or
    \let\mp@align\relax
  \fi
}

\define@keylist{2,color,gray!25,;2,angle,45,;
  2,scale,1,\def\mydo##1{\do ##1};5,align,center,\f@align;
  |color(red)\stopread|color(verbcolor);3,mybool,true,;
  5,weather,sunny,\protected@edef\VWeather{\val}}.
\end{krverbatim}
The \cs{\nr} and \cs{\val} macros are bin parameters defined by the \sty{xkeyval} package. \cs{\val} contains the user input for the current key and \cs{\nr} contains the numeral corresponding to the user input in the \cs{\CKVS} list, starting from 0 (zero). For example, in the \cx{\CKVS{align}} list, the \cs{\nr} values are \cs{center}~(0), \cs{right}~(1), \cs{left}~(2), and \cs{justified}~(3). These parameters thus refresh with the choice key and its user-supplied value.

Instead of defining the macro \cs{\f@align} before hand, we can submit its replacement text directly to the macro \cs{\define@keylist}, but, because \cs{\f@align} contains a conditional, some care is needed in doing so (see section~\ref{sec:conditionals}). Once the key \cs{align} has been defined, the macro \cs{\f@align} can be reused---perhaps to define other keys---even before the key \cs{align} is set. This is because it isn't \cs{\f@align} that is used in defining the key \cs{align} but its internal counterpart (\ie, a family-dependent internal of \cs{\f@align}, which is \cs{\fam@align@func}). In this way, the user can economize on tokens. The same applies to all the macros that may be used in defining keys.

Note the \cs{\stopread} command inserted above. Because of it, the key \cs{mybool} will not be read and defined; the rest (\ie, \cs{color}, \cs{angle}, \cs{scale} and \cs{align}) will be read and defined. All the entries for \cs{mybool} and \cs{weather} will instead be saved in the macro \cs{\KR@remainder}, possibly for some other uses.

Hundreds of keys can be defined efficiently in this way, using very few tokens.

As another example, we consider the following page setup keys:
\begin{krverbatim}
\CKVS{align}{center,right,left,justified}
\CKVS{election}{state,federal,congress,senate}
% |color(gray)\CKVS needs to be defined only once for each key in a family.|normalcolor

\define@keylist{%
  3,boolvar,true,;1,paperheight,\paperheight,;
  1,paperwidth,\paperwidth,\f@paperwidth;
  2,textheight,\textheight,\f@textheight;
  2,textwidth,\textwidth,\f@textwidth;
  1,evensidemargin,\evensidemargin,;
  5,align,center,\f@align;
  5,election,congress,;
  2,testdim,2cm,\long\def\f@testdim##1{A test dimension ##1
    \par\bigskip}%
  % |color(gray) Note the number of parameter characters
  % |color(gray) in the definition of \f@testdim.
}
\end{krverbatim}
which have the following trivial key macros:
\begin{krverbatim}
\def\f@textwidth{\AtBeginDocument{\wlog{`textwidth' %
  is \mp@textwidth}}}

\def\f@textheight{%
  \ifx\@empty\mp@textheight
    \wlog{`textheight' value empty}%
  \else
    \wlog{`textheight' value not empty}%
  \fi
}

\def\f@paperwidth{\wlog{`paperwidth' was defined as %
  ordinary key.}}
\newcommand\f@align{%
  \ifcase\nr\relax
    \def\mp@align{\centering}%
  \or
    \def\mp@align{\flushright}%
  \or
    \def\mp@align{\flushleft}%
  \or
    \let\mp@align\relax
  \fi
}
\end{krverbatim}
Again, once the keys have been defined, these macros can be reused.

The same set of keys can be defined via the starred form of \cs{\define@keylist}:
\begin{krverbatim}
\def\keylist{%
  3,boolvar,true,;1,paperheight,\paperheight,;
  1,paperwidth,\paperwidth,\f@paperwidth;
  2,textheight,\textheight,\f@textheight;
  2,textwidth,\textwidth,\f@textwidth;
  1,evensidemargin,\evensidemargin,;
  4,mytoggle,true,\let\settoggle\settog;
  5,align,center,\f@align;
  5,election,congress,;
  2,testdim,2cm,\long\def\f@testdim##1%
    {Do something with ##1}%
}
\define@keylist*\keylist.
\end{krverbatim}

Since the keys have been defined, they can now be set. In the following, we set only two of the keys:
\begin{krverbatim}
\setkeys[KV]{fam}{align=right,testdim=3cm}
\end{krverbatim}

The macro \cs{\mp@align} holds the value \cs{\flushright}, while
\begin{krverbatim}
\KV@fam@testdim
\end{krverbatim}
holds the macros:
\begin{krverbatim}
\def\mp@testdim{#1}
\long\def\f@testdim##1{A test dimension##1\par\bigskip},
\end{krverbatim}
where \cs{\#1} is the value submitted for the key \cs{testdim}.
Try \cx{\show\mp@align}, \cx{\show\KV@fam@testdim}, and \cx{\show\f@testdim} to confirm the above assertions.

The rest of the defined keys can now be set as follows:
\begin{krverbatim}
\setkeys[KV]{fam}{boolvar=true,paperheight,paperwidth,
  textheight,textwidth=6cm}
\end{krverbatim}
Try \cx{\show\ifmp@boolvar} to confirm that \cs{boolvar} is now \cs{<true>}; it was  originally set as \cs{<false>}. The macro \cs{\KV@fam@paperwidth} holds the function \cs{\f@paperwidth}; \cs{\mp@textheight} holds the value submitted to key \cs{textheight} at any instance of \cs{\setkeys}. By the above \cs{\setkeys}, only the default values of \cs{paperheight}, \cs{paperwidth}, and \cs{textheight} are presently available.

Instead of using macros to pass key macros and functions, it is also possible to use token registers. An example is provided below:
\begin{krverbatim}
\toks0={\long\def\f@testdim#1{A test dimension #1\par\bigskip}}

\define@keylist{3,boolvar,true,;2,testdim,2cm,\the\toks0}.
\end{krverbatim}
The advantage of using token registers is that the parameter characters need not be doubled in the token registers, unlike when using macros. The token register \cs{\toks0} can be reused as soon as the key \cs{testdim} is defined.

\subsection[Demonstrating an effect]%
  {Demonstrating the effect of limiting \textbackslash textwidth}

After defining and setting the keys above, the following tokens can be used in a source file to demonstrate the effect of setting the page setup keys shown above:
\begin{krverbatim}
\begin{center}
  \begin{minipage}{\mp@textwidth}
    \lipsum[1]
      % |color(gray)From the |emph(lipsum) package.
      % |color(gray)The |emph(blindtext) package can also be used.
  \end{minipage}
\end{center}

\lipsum[1]
\end{krverbatim}

\section{Input error}

Both boolean and choice keys issue error messages if the input is not valid, \ie, not in the list of admissible values. The default input error is defined by \cs{\KR@inputerr} macro to be
\begin{krverbatim}
\KR@err{Erroneous value `#1' for key `#2'}{%
  Please use the correct value for key `#2'.}.
\end{krverbatim}
\cs{\KR@inputerr} can be redefined by the user. It takes two arguments (\ie, value and key).

\section{Conditionals in key macros}
\label{sec:conditionals}

The \TeX{} conditional primitives \cs{\if} and \cs{\fi} cannot appear in the key macro when \cs{\define@keylist} is being invoked. The reason can be traced to the discussion on page~211 of the \TeX Book and the loop used in the \sty{keyreader} package to define keys. There are three approaches to resolving this problem, and the user can choose anyone he/she prefers.

\subsection{Burying conditionals in macros or token registers}

Key macros/functions involving conditional operations such as
\begin{krverbatim}
\ifmp@bool \do \fi
\end{krverbatim}
can be submitted to \cs{\define@keylist} via macros, as seen above. We give more examples below.

Suppose we want to submit the following:
\begin{krverbatim}
\define@keylist{3,bool,true,\ifmp@bool \do \fi}.
\end{krverbatim}
The presence of \cs{\if} and \cs{\fi} in the argument will trigger an error when \TeX{} is  scanning or skipping tokens, and, secondly, because of the loop and conditional used by the \sty{keyreader} package in defining keys. Neither \cs{\protect} nor \cs{\noexpand} is helpful here. One solution is to first define
\begin{krverbatim}
\def\f@bool{\ifmp@bool \do \fi}
\end{krverbatim}
and then do
\begin{krverbatim}
\define@keylist{3,bool,true,\f@bool},
\end{krverbatim}
which will execute \cs{\f@bool} when the key \cs{bool} is set. Once the key \cs{bool} has been defined by the above statement, the function \cs{\f@bool} may be  redefined and reused many times, any time, even before the setting of the key \cs{bool}. It isn't the function \cs{\f@bool} that is used in defining the key \cs{bool}, but an internal of \cs{\f@bool}.

As another example, we may do
\begin{krverbatim}
\def\f@abool{\ifmp@abool\def\do####1{%
  \def####1########1{\expandafter\expandafter\expandafter\in@
  \expandafter\expandafter\expandafter{\expandafter####1
  \expandafter}\expandafter{########1}}}\fi}

\define@keylist{3,abool,true,\f@abool}.
\end{krverbatim}

Token registers (including scratch token registers) can be used here economically instead of macros:
\begin{krverbatim}
\toks0{\ifmp@abool\def\do#1{%
  \def#1##1{\expandafter\expandafter\expandafter\in@
  \expandafter\expandafter\expandafter{\expandafter#1
  \expandafter}\expandafter{##1}}}\fi}

\toks1{\iftog{toggleone}{def\tempa#1{Use #1}}{}}

\define@keylist{3,abool,true,\the\toks0;
  4,toggleone,true,\the\toks1}

\setkeys[KV]{fam}{abool=true,toggleone=true}.
\end{krverbatim}
You can see the significant reduction in the number of parameter characters when using token registers. The token registers \cs{\toks0} and \cs{\toks1} can be reused to define many other keys.

\subsection{Using a ``dirty'' trick to submit the conditionals}
\label{sec:dirty-trick}

There are two downsides to the above approach of hiding conditionals in macros:
\begin{enumerate}
\item The macros have to be defined and, although they can be redefined and reused, they tend to defeat the initial aim of the package, which is to economize on tokens.
\item If the conditionals involve macro definitions as in the above example, the parameter characters have to be doubled in each instance, except when using token registers.
\end{enumerate}

Suppose we want to define a boolean key \cs{mybool} with the following key macro:
\begin{krverbatim}
\ifmp@mybool\def\hold##1{\def##1####1{####1}}\fi,
\end{krverbatim}
where the macro prefix is \cs{mp@} and the key family has been defined previously. Then, instead of hiding the conditional in a macro, we can go
\begin{krverbatim}
\define@keylist{3,mybool,true,
  \fif{mp@mybool}\def\hold##1{\def##1####1{####1}}\ffi}.
\end{krverbatim}
Here we have used \cx{\fif{mp@mybool}} and \cs{\ffi} for \cs{\ifmp@mybool} and \cs{\fi}, respectively, to hide the latter two from \TeX's scanning and skipping mechanism. Please note that \cx{\fif{mp@mybool}} requires that the argument \cs{<mp@mybool>} be enclosed in braces. Something like \cs{\fifmp@mybool} will be interpreted by \TeX{} as undefined control sequence when the key \cs{mybool} is being set.

Now, however, when setting the key \cs{mybool}, the user has to use \cs{\krsetkeys} instead of \sty{xkeyval}'s legacy \cs{\setkeys}. The command \cs{\krsetkeys} does understand that \cs{\fif} and \cs{\ffi} stand for \cs{\if} and \cs{\fi}, respectively, and have been used to ``deceive'' \TeX. \cs{\krsetkeys} has the same syntax as \cs{\setkeys}:
\begin{krverbatim}
\krsetkeys*+[key prefix]{key family}{keys=values}.
\end{krverbatim}
\cs{\krsetkeys} can in general be used in place of \cs{\setkeys}, even in instances (\ie, for keys) where \cs{\fif} and \cs{\ffi} have not been used.

In the case of conditionals starting with \cs{\ifcase}, a \cs{\noexpand} before the \cs{\ifcase} solves the problem:
\begin{krverbatim}
\CKVS{focus}{center,left,right,justified}

\define@keylist{5,focus,center,|color(red)\noexpand|color(verbcolor)\ifcase\nr\relax
  \def\mp@focus{\centering}\or\def\mp@focus{\flushright}
  \or\def\mp@focus{\flushleft}\or\let\mp@focus\relax\fi
}
\end{krverbatim}

\subsection{Using toggles}

Toggle switches, described in Section~\ref{sec:toggles}, can also be used to circumvent the problem of matching \cs{\if} and \cs{\fi} in difficult circumstances, since toggles aren't \TeX\ primitives. For example, the following works:
\begin{krverbatim}
\define@keylist{4,toggleone,true,
  \iftog{toggleone}{\def\temp{This is defined by a toggle}}{}}.
\end{krverbatim}
And, as noted in Section~\ref{sec:toggles}, toggles are very economical.

\section{Disabling keys}

The \sty{keyreader} package has modified the definition of \cs{\disable@keys} from the \sty{xkeyval} package to allow for bespoke warnings and error messages, without engendering any conflict with the legacy \cs{\disable@keys}. The new command is \cs{\krdisable@keys}; the use syntax remains the same as that of \cs{\disable@keys}:
\begin{krverbatim}
\krdisable@keys[<key prefix>]{<key family>}{<comma %
  separated list of keys to disable>}.
\end{krverbatim}

Any attempt to subsequently set a disabled key will prompt the following error message. (The \sty{xkeyval} package issues a warning in this case.) The error message can be modified by the user, but the ``names'' \cs{\KR@disabledkey@err} and \cs{\KR@disabledkey} should be retained.
\begin{krverbatim}
\def\KR@disabledkey@err{%
  \PackageError{keyreader}{%
    Key `\KR@disabledkey' has been disabled.}{%
    You can't set or reset it at this late stage.\MessageBreak
    You should have set it earlier in the\MessageBreak
    \string\documentclass\space or \string\usepackage
  }%
}
\end{krverbatim}
If the user attempts to disable an undefined key, the \sty{xkeyval} package issues a fatal error; the \sty{keyreader} package, on the other hand, issues a warning in the transcript .log file, since the situation isn't fatal to the outcome.

\section{Epilogue}

The are many commands available in the package for general use, but they are not documented here.

\end{document}

%%% End of file keyreader-guide.tex %%%