% !TEX program = pdflatex % % This is a test file demonstrating the keys3 experimental LaTeX3 % package. This file illustrates the methods made available by keys3 % for managing key-value input. It also acts as a check, as almost all % of the keys3 methods are used (with known output) and because a number % of errors are deliberately raised. \documentclass{article} \usepackage{keys3,xparse} \usepackage[parfill]{parskip} % The document commands for using keys is very simple. \ExplSyntaxOn \DeclareDocumentCommand \SetModuleKeys { m } { \keys_set:nn { module } {#1} } \ExplSyntaxOff \begin{document} % Each test starts with a short piece of text explaining the property % being used. Under this, the expected output is given, followed % if relevant by the text of any error messages expected. % Test one: Simply creating a key with one argument and then using it. % Notice that the text length determines the limits of the argument: % spaces at either end are ignored. Literal spaces between text are % counted, as are those enclosed in braces. % ---------------------------------------------------------------------- % You said: `Hello World' % You said: ` Hello World ' % You said: `' % ---------------------------------------------------------------------- \ExplSyntaxOn \keys_show:nn { module } {unknown} \keys_set:nn { module } { clive = india } \keys_define:nn { module } { key .code:n = {You~said:~`#1'\\} } \ExplSyntaxOff \SetModuleKeys{ key = Hello World , key = { Hello World }, key } % Test two: Creating a multiple-argument key. Here, the arguments % given need to be at least as many as those required by the code! % ---------------------------------------------------------------------- % You said: `A', `B', `C', D'. % You said: `AAA', `BBB', `CCC', ` DDD'. % ---------------------------------------------------------------------- \ExplSyntaxOn \keys_define:nn { module } { key .code:Nn = 4 {You said:~`#1',~`#2',~`#3',~`#4'.\\}, } \ExplSyntaxOff \SetModuleKeys{ key = ABCD, key = {AAA}{BBB} {CCC} { DDD} } % Test three: Variants of .code:n and .code:Nn exist which carry out a % full expansion on code definition. First the :x variant is tested. % ---------------------------------------------------------------------- % Temp holds: ABC % Temp hold: 123 % ---------------------------------------------------------------------- \newcommand*{\temp}{123} \ExplSyntaxOn \keys_define:nn { module } { key-one .code:n = Temp~holds:~\temp\\, key-two .code:x = Temp~holds:~\temp, } \ExplSyntaxOff \renewcommand*{\temp}{ABC} \SetModuleKeys{ key-one, key-two } % Now the :Nx version % ---------------------------------------------------------------------- % Arguments: A, B. Temp holds: ABC % Arguments: 1, 2. Temp hold: 123 % ---------------------------------------------------------------------- \renewcommand*{\temp}{123} \ExplSyntaxOn \keys_define:nn { module } { key-one .code:Nn = 2 {Arguments:~#1,~#2.~Temp~holds:~\temp\\}, key-two .code:Nx = 2 {Arguments:~#1,~#2.~Temp~holds:~\temp}, } \ExplSyntaxOff \renewcommand*{\temp}{ABC} \SetModuleKeys{ key-one = {A} {B}, key-two = {1} {2} } % Test four: Values can be required and forbidden with the % .value_required: and .value_forbidden: properties. % ---------------------------------------------------------------------- % All okay % All okay % ---------------------------------------------------------------------- % The key `module/key-one' cannot taken a value: % the given input `Not allowed' is being ignored. % % The key `module/key-two' requires a value % and is being ignored. % ---------------------------------------------------------------------- \ExplSyntaxOn \keys_define:nn { module } { key-one .code:n = All okay\\, key-one .value_forbidden:, key-two .code:n = #1, key-two .value_required: } \ExplSyntaxOff \SetModuleKeys{ key-one, key-one = Not allowed, key-two = All okay, key-two } % Test five: Keys can be given a default value, to be used if nothing is % specified by the user. This can be done by name or by value. % ---------------------------------------------------------------------- % Default % Real % Stuff % Real % Literal % Real % ---------------------------------------------------------------------- \ExplSyntaxOn \renewcommand*{\temp}{Stuff} \keys_define:nn { module } { key-one .code:n = #1\\, key-one .default:n = \temp, key-two .code:n = #1\\, key-two .default:V = \temp, key-three .code:n = #1\\, key-three .default:n = Literal, } \ExplSyntaxOff \renewcommand*{\temp}{Default} \SetModuleKeys{ key-one, key-one = Real, key-two, key-two = Real, key-three, key-three = Real } % Test six: Keys can be created to store data both locally and % globally. This is illustrated using token list variables. % ---------------------------------------------------------------------- % Some content % Outside % Some content % Some content % ---------------------------------------------------------------------- \ExplSyntaxOn \tl_new:Nn \l_temp_tl {Outside} \tl_new:Nn \g_temp_tl {Outside} \keys_define:nn { module } { key-one .set:N = \l_temp_tl, key-two .set:N = \g_temp_tl, } \begingroup \SetModuleKeys{ key-one = Some~content } \l_temp_tl\\ \endgroup \l_temp_tl\\ \begingroup \SetModuleKeys{ key-two = Some~content } \g_temp_tl\\ \endgroup \g_temp_tl\\ \ExplSyntaxOff % Test seven: An expanded version of .set:N is available. % ---------------------------------------------------------------------- % Unexpanded % Expanded % ---------------------------------------------------------------------- \ExplSyntaxOn \tl_set:Nn \l_temp_tl {Expanded} \tl_new:N \l_tempa_tl \tl_new:N \l_tempb_tl \keys_define:nn { module } { key-one .set:N = \l_tempa_tl, key-two .set_x:N = \l_tempb_tl, } \SetModuleKeys{ key-one = \l_temp_tl, key-two = \l_temp_tl, } \tl_set:Nn \l_temp_tl {Unxpanded} \l_tempa_tl\\ \l_tempb_tl\\ \ExplSyntaxOff % Test eight: Choices can be created either from a list of options or % one by one. Both are tested here by creating a list then adding to it % with an extra key. Unknown choices lead to an error message. % ---------------------------------------------------------------------- % Choice `a' is number 1 % Choice `b' is number 2 % Choice `c' is number 3 % An extra choice % ---------------------------------------------------------------------- % Choice `e' unknown for key `module/key': % the key is being ignored. % ---------------------------------------------------------------------- \ExplSyntaxOn \keys_define:nn { module } { key .generate_choices:nn = {a,b,c} { Choice~`\l_keys_choice_tl'~is~number~\int_use:N \l_keys_choice_int\\ }, key/d .code:n = An~extra~choice \\ } \ExplSyntaxOff \SetModuleKeys{ key = a, key = b, key = c, key = d, key = e } % Test nine: A completely unknown key should cause an error. % ---------------------------------------------------------------------- % The key `module/unknown key' is unknown and is being ignored. % ---------------------------------------------------------------------- \SetModuleKeys{ unknown key = some value } % Test ten: If the special `unknown' key has been set up, however, % unknown input can be re-directed. % ---------------------------------------------------------------------- % You tried to set key `unknown key' to `some value' % ---------------------------------------------------------------------- \ExplSyntaxOn \keys_define:nn { module } { unknown .code:n = You~tried~to~set~key~`\l_keys_key_tl'~to~`#1' } \ExplSyntaxOff \SetModuleKeys{ unknown key = some~value } \end{document}