diff options
author | Karl Berry <karl@freefriends.org> | 2013-07-12 22:54:42 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2013-07-12 22:54:42 +0000 |
commit | 60ede63177ff54dd8d1934012fbecce179a633ee (patch) | |
tree | 9dbd9e4608c9a0caa9864fedf49f0a2aea36fedf /Master/texmf-dist/source/latex/l3kernel/l3keys.dtx | |
parent | c2d4fa6f59f3c566ccd85e3b250f0a27485bbaea (diff) |
l3 (12jul13)
git-svn-id: svn://tug.org/texlive/trunk@31181 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3keys.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3keys.dtx | 801 |
1 files changed, 430 insertions, 371 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx b/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx index 3d38853224a..3ad30990c73 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx @@ -35,7 +35,7 @@ % %<*driver|package> \RequirePackage{l3bootstrap} -\GetIdInfo$Id: l3keys.dtx 4461 2013-02-24 18:55:17Z joseph $ +\GetIdInfo$Id: l3keys.dtx 4544 2013-07-12 07:14:52Z joseph $ {L3 Experimental key-value interfaces} %</driver|package> %<*driver> @@ -68,21 +68,22 @@ % \begin{documentation} % % The key--value method is a popular system for creating large numbers -% of settings for controlling function or package behaviour. For the -% user, the system normally results in input of the form +% of settings for controlling function or package behaviour. The +% system normally results in input of the form % \begin{verbatim} -% \PackageControlMacro{ +% \MyModuleSetup{ % key-one = value one, % key-two = value two % } % \end{verbatim} % or % \begin{verbatim} -% \PackageMacro[ +% \MyModuleMacro[ % key-one = value one, % key-two = value two -% ]{argument}. +% ]{argument} % \end{verbatim} +% for the user. % % The high level functions here are intended as a method to create % key--value controls. Keys are themselves created using a key--value @@ -90,15 +91,15 @@ % required. Each key is created by setting one or more \emph{properties} % of the key: % \begin{verbatim} -% \keys_define:nn { module } +% \keys_define:nn { mymodule } % { % key-one .code:n = code including parameter #1, -% key-two .tl_set:N = \l_module_store_tl +% key-two .tl_set:N = \l_mymodule_store_tl % } % \end{verbatim} % These values can then be set as with other key--value approaches: % \begin{verbatim} -% \keys_set:nn { module } +% \keys_set:nn { mymodule } % { % key-one = value one, % key-two = value two @@ -108,15 +109,15 @@ % At a document level, \cs{keys_set:nn} will be used within a % document function, for example % \begin{verbatim} -% \DeclareDocumentCommand \SomePackageSetup { m } -% { \keys_set:nn { module } { #1 } } -% \DeclareDocumentCommand \SomePackageMacro { o m } -% { -% \group_begin: -% \keys_set:nn { module } { #1 } -% % Main code for \SomePackageMacro -% \group_end: -% } +% \DeclareDocumentCommand \MyModuleSetup { m } +% { \keys_set:nn { mymodule } { #1 } } +% \DeclareDocumentCommand \MyModuleMacro { o m } +% { +% \group_begin: +% \keys_set:nn { mymodule } { #1 } +% % Main code for \MyModuleMacro +% \group_end: +% } % \end{verbatim} % % Key names may contain any tokens, as they are handled internally @@ -126,13 +127,13 @@ % groups. Functions and variables are \emph{not} expanded when creating % key names, and so % \begin{verbatim} -% \tl_set:Nn \l_module_tmp_tl { key } -% \keys_define:nn { module } +% \tl_set:Nn \l_mymodule_tmp_tl { key } +% \keys_define:nn { mymodule } % { -% \l_module_tmp_tl .code:n = code +% \l_mymodule_tmp_tl .code:n = code % } % \end{verbatim} -% will create a key called \cs{l_module_tmp_tl}, and not one called +% will create a key called \cs{l_mymodule_tmp_tl}, and not one called % \texttt{key}. % % \section{Creating keys} @@ -164,32 +165,36 @@ % \end{function} % % The various properties available take either no arguments at -% all, or require exactly one argument. This is indicated in the +% all, or require one or more arguments. This is indicated in the % name of the property using an argument specification. In the following % discussion, each property is illustrated attached to an % arbitrary \meta{key}, which when used may be supplied with a % \meta{value}. All key \emph{definitions} are local. % -% \begin{function}{.bool_set:N, .bool_gset:N} +% \begin{function}[updated = 2013-07-08] +% {.bool_set:N, .bool_set:c, .bool_gset:N, .bool_gset:c} % \begin{syntax} % \meta{key} .bool_set:N = \meta{boolean} % \end{syntax} % Defines \meta{key} to set \meta{boolean} to \meta{value} (which % must be either \texttt{true} or \texttt{false}). If the variable -% does not exist, it will be created at the point that the key is -% set up. +% does not exist, it will be created globally at the point that +% the key is set up. % \end{function} % -% \begin{function}[added = 2011-08-28] -% {.bool_set_inverse:N, .bool_gset_inverse:N} +% \begin{function}[added = 2011-08-28, updated = 2013-07-08] +% { +% .bool_set_inverse:N, .bool_set_inverse:c, +% .bool_gset_inverse:N, .bool_gset_inverse:c +% } % \begin{syntax} % \meta{key} .bool_set_inverse:N = \meta{boolean} % \end{syntax} % Defines \meta{key} to set \meta{boolean} to the logical % inverse of \meta{value} (which must be either \texttt{true} or % \texttt{false}). -% If the \meta{boolean} does not exist, it will be created at the point -% that the key is set up. +% If the \meta{boolean} does not exist, it will be created globally +% at the point that the key is set up. % \end{function} % % \begin{function}{.choice:} @@ -198,10 +203,11 @@ % \end{syntax} % Sets \meta{key} to act as a choice key. Each valid choice % for \meta{key} must then be created, as discussed in -% section~\ref{sec:choice}. +% section~\ref{sec:l3keys:choice}. % \end{function} % -% \begin{function}[added = 2011-08-21]{.choices:nn} +% \begin{function}[added = 2011-08-21, updated = 2013-07-10] +% {.choices:nn, .choices:Vn, .choices:on, .choices:xn} % \begin{syntax} % \meta{key} .choices:nn \meta{choices} \meta{code} % \end{syntax} @@ -210,22 +216,10 @@ % \cs{l_keys_choice_tl} will be the name of the choice made, and % \cs{l_keys_choice_int} will be the position of the choice in the list % of \meta{choices} (indexed from~$1$). -% Choices are discussed in detail in section~\ref{sec:choice}. +% Choices are discussed in detail in section~\ref{sec:l3keys:choice}. % \end{function} % -% \begin{function}{.choice_code:n, .choice_code:x} -% \begin{syntax} -% \meta{key} .choice_code:n = \meta{code} -% \end{syntax} -% Stores \meta{code} for use when \texttt{.generate_choices:n} creates -% one or more choice sub-keys of the current key. Inside \meta{code}, -% \cs{l_keys_choice_tl} will expand to the name of the choice made, and -% \cs{l_keys_choice_int} will be the position of the choice in the list -% given to \texttt{.generate_choices:n}. Choices are discussed in -% detail in section~\ref{sec:choice}. -% \end{function} -% -% \begin{function}[added=2011/09/11] +% \begin{function}[added=2011-09-11] % {.clist_set:N, .clist_set:c, .clist_gset:N, .clist_gset:c} % \begin{syntax} % \meta{key} .clist_set:N = \meta{comma list variable} @@ -233,21 +227,22 @@ % Defines \meta{key} to set \meta{comma list variable} to \meta{value}. % Spaces around commas and empty items will be stripped. % If the variable does not exist, it -% will be created at the point that the key is set up. +% will be created globally at the point that the key is set up. % \end{function} % -% \begin{function}{.code:n, .code:x} +% \begin{function}[updated = 2013-07-10]{.code:n} % \begin{syntax} % \meta{key} .code:n = \meta{code} % \end{syntax} % Stores the \meta{code} for execution when \meta{key} is used. The -% The \meta{code} can include one parameter ("#1"), which will be the +% The \meta{code} can include one parameter (|#1|), which will be the % \meta{value} given for the \meta{key}. The \texttt{x}-type variant % will expand \meta{code} at the point where the \meta{key} is % created. % \end{function} % -% \begin{function}{.default:n, .default:V} +% \begin{function}[updated = 2013-07-09] +% {.default:n, .default:V, .default:o, .default:x} % \begin{syntax} % \meta{key} .default:n = \meta{default} % \end{syntax} @@ -255,12 +250,12 @@ % value is given. This will be used if only the key name is given, % but not if a blank \meta{value} is given: % \begin{verbatim} -% \keys_define:nn { module } +% \keys_define:nn { mymodule } % { % key .code:n = Hello~#1, % key .default:n = World % } -% \keys_set:nn { module } +% \keys_set:nn { mymodule } % { % key = Fred, % Prints 'Hello Fred' % key, % Prints 'Hello World' @@ -275,7 +270,7 @@ % \end{syntax} % Defines \meta{key} to set \meta{dimension} to \meta{value} (which % must a dimension expression). If the variable does not exist, it -% will be created at the point that the key is set up. +% will be created globally at the point that the key is set up. % \end{function} % % \begin{function}{.fp_set:N, .fp_set:c, .fp_gset:N, .fp_gset:c} @@ -283,29 +278,18 @@ % \meta{key} .fp_set:N = \meta{floating point} % \end{syntax} % Defines \meta{key} to set \meta{floating point} to \meta{value} -% (which must a floating point number). If the variable does not exist, -% it will be created at the point that the key is set up. +% (which must a floating point expression). If the variable does not exist, +% it will be created globally at the point that the key is set up. % \end{function} % -% \begin{function}{.generate_choices:n} -% \begin{syntax} -% \meta{key} .generate_choices:n = \Arg{list} -% \end{syntax} -% This property will mark \meta{key} as a multiple choice key, -% and will use the \meta{list} to define the choices. The \meta{list} -% should consist of a comma-separated list of choice names. Each -% choice will be set up to execute \meta{code} as set using -% \texttt{.choice_code:n} (or \texttt{.choice_code:x}). Choices are -% discussed in detail in section~\ref{sec:choice}. -% \end{function} -% -% \begin{function}[added = 2012-06-02]{.initial:n, .initial:V} +% \begin{function}[updated = 2013-07-09] +% {.initial:n, .initial:V, .initial:o, .initial:x} % \begin{syntax} % \meta{key} .initial:n = \meta{value} % \end{syntax} % Initialises the \meta{key} with the \meta{value}, equivalent to % \begin{quote} -% \cs{keys_set:nn} \marg{module} \{ \meta{key} = \meta{value} \} +% \cs{keys_set:nn} \Arg{module} \{ \meta{key} = \meta{value} \} % \end{quote} % \end{function} % @@ -315,10 +299,10 @@ % \end{syntax} % Defines \meta{key} to set \meta{integer} to \meta{value} (which % must be an integer expression). If the variable does not exist, it -% will be created at the point that the key is set up. +% will be created globally at the point that the key is set up. % \end{function} % -% \begin{function}{.meta:n, .meta:x} +% \begin{function}[updated = 2013-07-10]{.meta:n} % \begin{syntax} % \meta{key} .meta:n = \Arg{keyval list} % \end{syntax} @@ -327,6 +311,17 @@ % is used, then the value will be passed through to the subsidiary % \meta{keys} for processing (as |#1|). % \end{function} +% +% \begin{function}[added = 2013-07-10]{.meta:nn} +% \begin{syntax} +% \meta{key} .meta:nn = \Arg{path} \Arg{keyval list} +% \end{syntax} +% Makes \meta{key} a meta-key, which will set \meta{keyval list} in +% one go using the \meta{path} in place of the current one. +% If \meta{key} is given with a value at the time the key +% is used, then the value will be passed through to the subsidiary +% \meta{keys} for processing (as |#1|). +% \end{function} % % \begin{function}[added = 2011-08-21]{.multichoice:} % \begin{syntax} @@ -334,12 +329,11 @@ % \end{syntax} % Sets \meta{key} to act as a multiple choice key. Each valid choice % for \meta{key} must then be created, as discussed in -% section~\ref{sec:choice}. -% -% \textbf{This property is experimental.} +% section~\ref{sec:l3keys:choice}. % \end{function} % -% \begin{function}[added = 2011-08-21]{.multichoices:nn} +% \begin{function}[added = 2011-08-21, updated = 2013-07-10] +% {.multichoices:nn, .multichoices:Vn, .multichoices:on, .multichoices:xn} % \begin{syntax} % \meta{key} .multichoices:nn \meta{choices} \meta{code} % \end{syntax} @@ -349,9 +343,7 @@ % \cs{l_keys_choice_tl} will be the name of the choice made, and % \cs{l_keys_choice_int} will be the position of the choice in the list % of \meta{choices} (indexed from~$1$). -% Choices are discussed in detail in section~\ref{sec:choice}. -% -% \textbf{This property is experimental.} +% Choices are discussed in detail in section~\ref{sec:l3keys:choice}. % \end{function} % % \begin{function}{.skip_set:N, .skip_set:c, .skip_gset:N, .skip_gset:c} @@ -360,7 +352,7 @@ % \end{syntax} % Defines \meta{key} to set \meta{skip} to \meta{value} (which % must be a skip expression). If the variable does not exist, it -% will be created at the point that the key is set up. +% will be created globally at the point that the key is set up. % \end{function} % % \begin{function}{.tl_set:N, .tl_set:c, .tl_gset:N, .tl_gset:c} @@ -368,8 +360,8 @@ % \meta{key} .tl_set:N = \meta{token list variable} % \end{syntax} % Defines \meta{key} to set \meta{token list variable} to \meta{value}. -% If the variable does not exist, it will be created at the point that -% the key is set up. +% If the variable does not exist, it will be created globally +% at the point that the key is set up. % \end{function} % % \begin{function}{.tl_set_x:N, .tl_set_x:c, .tl_gset_x:N, .tl_gset_x:c} @@ -379,7 +371,7 @@ % Defines \meta{key} to set \meta{token list variable} to \meta{value}, % which will be subjected to an \texttt{x}-type expansion % (\emph{i.e.}~using \cs{tl_set:Nx}). If the variable does not exist, -% it will be created at the point that the key is set up. +% it will be created globally at the point that the key is set up. % \end{function} % % \begin{function}{.value_forbidden:} @@ -410,7 +402,7 @@ % \end{verbatim} % or to the key name: % \begin{verbatim} -% \keys_define:nn { module } +% \keys_define:nn { mymodule } % { subgroup / key .code:n = code } % \end{verbatim} % As illustrated, the best choice of token for sub-dividing keys in @@ -422,7 +414,7 @@ % particularly relevant to making multiple choices. % % \section{Choice and multiple choice keys} -% \label{sec:choice} +% \label{sec:l3keys:choice} % % The \pkg{l3keys} system supports two types of choice key, in which a series % of pre-defined input values are linked to varying implementations. Choice @@ -433,7 +425,7 @@ % Mutually-exclusive choices are created by setting the \texttt{.choice:} % property: % \begin{verbatim} -% \keys_define:nn { module } +% \keys_define:nn { mymodule } % { key .choice: } % \end{verbatim} % For keys which are set up as choices, the valid choices are generated @@ -442,53 +434,29 @@ % % In many cases, choices execute similar code which is dependant only % on the name of the choice or the position of the choice in the -% list of choices. Here, the keys can share the same code, and can -% be rapidly created using the \texttt{.choice_code:n} and -% \texttt{.generate_choices:n} properties: -% \begin{verbatim} -% \keys_define:nn { module } -% { -% key .choice_code:n = -% { -% You~gave~choice~'\int_use:N \l_keys_choice_tl',~ -% which~is~in~position~ -% \int_use:N \l_keys_choice_int \c_space_tl -% in~the~list. -% }, -% key .generate_choices:n = -% { choice-a, choice-b, choice-c } -% } -% \end{verbatim} -% Following common computing practice, \cs{l_keys_choice_int} is -% indexed from~$1$. -% -% The same approach is also implemented by the \emph{experimental} -% property \texttt{.choices:nn}. This combines the functionality of -% \texttt{.choice_code:n} and \texttt{.generate_choices:n} into one -% property: +% list of all possibilities. Here, the keys can share the same code, and can +% be rapidly created using the \texttt{.choices:nn} property. % \begin{verbatim} -% \keys_define:nn { module } +% \keys_define:nn { mymodule } % { % key .choices:nn = % { choice-a, choice-b, choice-c } % { -% You~gave~choice~'\int_use:N \l_keys_choice_tl',~ -% which~is~in~position~ -% \int_use:N \l_keys_choice_int \c_space_tl +% You~gave~choice~'\tl_use:N \l_keys_choice_tl',~ +% which~is~in~position~\int_use:N \l_keys_choice_int \c_space_tl % in~the~list. % } % } % \end{verbatim} -% Note that the \texttt{.choices:nn} property should \emph{not} be mixed with -% use of \texttt{.generate_choices:n}. +% The index \cs{l_keys_choice_int} in the list of choices starts at~$1$. % % \begin{variable}{\l_keys_choice_int, \l_keys_choice_tl} -% Inside the code block for a choice generated using -% \texttt{.generate_choice:} or \texttt{.choices:nn}, -% the variables \cs{l_keys_choice_tl} and -% \cs{l_keys_choice_int} are available to indicate the name of the -% current choice, and its position in the comma list. The position -% is indexed from $0$. +% Inside the code block for a choice generated using \texttt{.choices:nn}, +% the variables \cs{l_keys_choice_tl} and \cs{l_keys_choice_int} are +% available to indicate the name of the current choice, and its position in +% the comma list. The position is indexed from~$1$. Note that, as with +% standard key code generated using \texttt{.code:n}, the value passed to +% the key (i.e.~the choice name) is also available as |#1|. % \end{variable} % % On the other hand, it is sometimes useful to create choices which @@ -496,32 +464,54 @@ % by setting the \texttt{.choice:} property of a key, then manually % defining sub-keys. % \begin{verbatim} -% \keys_define:nn { module } +% \keys_define:nn { mymodule } % { % key .choice:, % key / choice-a .code:n = code-a, % key / choice-b .code:n = code-b, % key / choice-c .code:n = code-c, % } -%\end{verbatim} +% \end{verbatim} % % It is possible to mix the two methods, but manually-created choices % should \emph{not} use \cs{l_keys_choice_tl} or \cs{l_keys_choice_int}. % These variables do not have defined behaviour when used outside of -% code created using \texttt{.generate_choices:n} +% code created using \texttt{.choices:nn} % (\emph{i.e.}~anything might happen). -% +% +% It is possible to allow choice keys to take values which have not previously +% been defined by adding code for the special \texttt{unknown} choice. The +% general behavior of the \texttt{unknown} key is described in +% Section~\ref{sec:l3keys:unknown}. A typical example in the case of a choice +% would be to issue a custom error message: +% \begin{verbatim} +% \keys_define:nn { mymodule } +% { +% key .choice:, +% key / choice-a .code:n = code-a, +% key / choice-b .code:n = code-b, +% key / choice-c .code:n = code-c, +% key / unknown .code:n = +% \msg_error:nnxxx { mymodule } { unknown-choice } +% { key } % Name of choice key +% { choice-a , choice-b , choice-c } % Valid choices +% { \exp_not:n {#1} } % Invalid choice given +% % +% % +% } +% \end{verbatim} +% % Multiple choices are created in a very similar manner to mutually-exclusive % choices, using the properties \texttt{.multichoice:} and % \texttt{.multichoices:nn}. As with mutually exclusive choices, multiple % choices are define as sub-keys. Thus both % \begin{verbatim} -% \keys_define:nn { module } +% \keys_define:nn { mymodule } % { % key .multichoices:nn = % { choice-a, choice-b, choice-c } % { -% You~gave~choice~'\int_use:N \l_keys_choice_tl',~ +% You~gave~choice~'\tl_use:N \l_keys_choice_tl',~ % which~is~in~position~ % \int_use:N \l_keys_choice_int \c_space_tl % in~the~list. @@ -530,28 +520,36 @@ % \end{verbatim} % and % \begin{verbatim} -% \keys_define:nn { module } +% \keys_define:nn { mymodule } % { % key .multichoice:, % key / choice-a .code:n = code-a, % key / choice-b .code:n = code-b, % key / choice-c .code:n = code-c, % } -%\end{verbatim} -% are valid. The \texttt{.multichoices:nn} property causes -% \cs{l_keys_choice_tl} and \cs{l_keys_choice_int} to be set in exactly -% the same way as described for \texttt{.choices:nn}. -% -% When multiple choice keys are set, the value is treated as a comma-separated -% list: +% \end{verbatim} +% are valid. +% +% When a multiple choice key is set % \begin{verbatim} -% \keys_set:nn { module } +% \keys_set:nn { mymodule } % { % key = { a , b , c } % 'key' defined as a multiple choice % } -%\end{verbatim} -% Each choice will be applied in turn, with the usual handling of unknown -% values. +% \end{verbatim} +% each choice is applied in turn, equivalent to a \texttt{clist} mapping or +% to applying each value individually: +% \begin{verbatim} +% \keys_set:nn { mymodule } +% { +% key = a , +% key = b , +% key = c , +% } +% \end{verbatim} +% Thus each separate choice will have passed to it the +% \cs{l_keys_choice_tl} and \cs{l_keys_choice_int} in exactly +% the same way as described for \texttt{.choices:nn}. % % \section{Setting keys} % @@ -565,37 +563,51 @@ % by defining a special \texttt{unknown} key: this will be illustrated % later. % \end{function} +% +% \begin{variable}{\l_keys_key_tl, \l_keys_path_tl, \l_keys_value_tl} +% For each key processed, information of the full \emph{path} of the +% key, the \emph{name} of the key and the \emph{value} of the key is +% available within three token list variables. These may be used within +% the code of the key. +% +% The \emph{value} is everything after the \texttt{=}, which may be +% empty if no value was given. This is stored in \cs{l_keys_value_tl}, and +% is not processed in any way by \cs{keys_set:nn}. +% +% The \emph{path} of the key is a \enquote{full} description of the key, +% and is unique for each key. It consists of the module and full key name, +% thus for example +% \begin{verbatim} +% \keys_set:nn { mymodule } { key-a = some-value } +% \end{verbatim} +% has path \texttt{mymodule/key-a} while +% \begin{verbatim} +% \keys_set:nn { mymodule } { subset / key-a = some-value } +% \end{verbatim} +% has path \texttt{mymodule/subset/key-a}. This information is stored in +% \cs{l_keys_path_tl}, and will have been processed by \cs{tl_to_str:n}. +% +% The \emph{name} of the key is the part of the path after the last +% \texttt{/}, and thus is not unique. In the preceding examples, both keys +% have name \texttt{key-a} despite having different paths. This information +% is stored in \cs{l_keys_key_tl}, and will have been processed by +% \cs{tl_to_str:n}. +% \end{variable} +% +% \section{Handling of unknown keys} +% \label{sec:l3keys:unknown} % -% If a key is not known, \cs{keys_set:nn} will look for a special -% \texttt{unknown} key for the same module. This mechanism can be -% used to create new keys from user input. +% If a key has not previously been defined (is unknown), \cs{keys_set:nn} will +% look for a special \texttt{unknown} key for the same module, and if this is +% not defined raises an error indicating that the key name was unknown. This +% mechanism can be used for example to issue custom error texts. % \begin{verbatim} -% \keys_define:nn { module } +% \keys_define:nn { mymodule } % { % unknown .code:n = % You~tried~to~set~key~'\l_keys_key_tl'~to~'#1'. % } -%\end{verbatim} -% -% \begin{variable}{\l_keys_key_tl} -% When processing an unknown key, the name of the key is available -% as \cs{l_keys_key_tl}. Note that this will have been processed -% using \cs{tl_to_str:n}. -% \end{variable} -% -% \begin{variable}{\l_keys_path_tl} -% When processing an unknown key, the path of the key used is available -% as \cs{l_keys_path_tl}. Note that this will have been processed -% using \cs{tl_to_str:n}. -% \end{variable} -% -% \begin{variable}{\l_keys_value_tl} -% When processing an unknown key, the value of the key is available as -% \cs{l_keys_value_tl}. Note that this will be empty if no value was given -% for the key. -% \end{variable} -% -% \section{Setting known keys only} +% \end{verbatim} % % \begin{function}[added = 2011-08-23] % { @@ -603,13 +615,16 @@ % \keys_set_known:nvN, \keys_set_known:noN % } % \begin{syntax} -% \cs{keys_set_known:nn} \Arg{module} \Arg{keyval list} \meta{clist} +% \cs{keys_set_known:nn} \Arg{module} \Arg{keyval list} \meta{tl} % \end{syntax} -% Parses the \meta{keyval list}, and sets those keys which are defined -% for \meta{module}. Any keys which are unknown are not processed further -% by the parser. +% In some cases, the desired behavior is to simply ignore unknown keys, +% collecting up information on these for later processing. The +% \cs{keys_set_known:nnN} function parses the \meta{keyval list}, and sets +% those keys which are defined for \meta{module}. Any keys which are unknown +% are not processed further by the parser. % The key--value pairs for each \emph{unknown} key name will be -% stored in the \meta{clist}. +% stored in the \meta{tl} in a comma-separated form (\emph{i.e.}~an edited +% version of the \meta{keyval list}). % \end{function} % % \section{Utility functions for keys} @@ -629,7 +644,7 @@ % \cs{keys_if_choice_exist:nnnTF} \meta{module} \meta{key} \meta{choice} \Arg{true code} \Arg{false code} % \end{syntax} % Tests if the \meta{choice} is defined for the \meta{key} within the -% \meta{module},, \emph{i.e.}~if any code has been defined for +% \meta{module}, \emph{i.e.}~if any code has been defined for % \meta{key}/\meta{choice}. The test is \texttt{false} if the \meta{key} % itself is not defined. % \end{function} @@ -657,7 +672,7 @@ % braces, spaces and the category codes of separators. % % While the functions described earlier are used as a high-level interface -% for processing such input, in especial circumstances you may wish to use +% for processing such input, in special circumstances you may wish to use % a lower-level approach. % The low-level parsing system converts a \meta{key--value list} % into \meta{keys} and associated \meta{values}. After the parsing phase @@ -665,15 +680,16 @@ % available for further processing. This processing is not carried out by the % low-level parser itself, and so the parser requires the names of % two functions along with the key--value list. One function is -% needed to process key--value pairs (\emph{i.e}~two arguments), -% and a second function if required for keys given without arguments -% (\emph{i.e.}~a single argument). +% needed to process key--value pairs (it receives two arguments), +% and a second function is required for keys given without any value +% (it is called with a single argument). % -% The parser does not double |#| tokens or expand any input. The tokens -% |=| and |,| are corrected so that the parser does not \enquote{miss} +% The parser does not double |#| tokens or expand any input. Active +% tokens |=| and |,| appearing at the outer level of braces are converted +% to category \enquote{other} (12) so that the parser does not \enquote{miss} % any due to category code changes. Spaces are removed from the ends -% of the keys and values. Values which are given in braces will have -% exactly one set removed, thus +% of the keys and values. Keys and values which are given in braces +% will have exactly one set removed (after space trimming), thus % \begin{verbatim} % key = {value here}, % \end{verbatim} @@ -710,8 +726,8 @@ % Note that there is a difference between an empty value (an equals % sign followed by nothing) and a missing value (no equals sign at % all). Spaces are trimmed from the ends of the \meta{key} and \meta{value}, -% and any \emph{outer} set of braces are removed from the \meta{value} as -% part of the processing. +% then one \emph{outer} set of braces is removed from the \meta{key} +% and \meta{value} as part of the processing. % \end{function} % % \end{documentation} @@ -733,7 +749,7 @@ % \end{macrocode} % % \subsection{Low-level interface} -% +% % \begin{macrocode} %<@@=keyval> % \end{macrocode} @@ -741,7 +757,8 @@ % For historical reasons this code uses the `keyval' module prefix. % % \begin{variable}{\g_@@_level_int} -% For nesting purposes an integer is needed for the current level. +% To allow nesting of \cs{keyval_parse:NNn}, an integer is needed for +% the current level. % \begin{macrocode} \int_new:N \g_@@_level_int % \end{macrocode} @@ -763,8 +780,8 @@ \tl_new:N \l_@@_sanitise_tl \tl_new:N \l_@@_parse_tl % \end{macrocode} -%\end{variable} -%\end{variable} +% \end{variable} +% \end{variable} % % \begin{macro}{\@@_parse:n} % The parsing function first deals with the category codes for @@ -817,7 +834,7 @@ % \end{macro} % % \begin{macro}{\@@_split_key_value:w} -% \begin{macro}[aux]{\@@_split_key_value:wTF} +% \begin{macro}[aux, EXP]{\@@_split_key_value:wTF} % The key and value are handled separately. First the key is grabbed and % saved as \cs{l_@@_key_tl}. Then a check is need to see if there is % a value at all: if not then the key name is simply added to the output. @@ -946,7 +963,7 @@ % \end{macrocode} % % \subsection{Constants and variables} -% +% % \begin{macrocode} %<@@=keys> % \end{macrocode} @@ -1081,8 +1098,11 @@ \cs_if_exist:cTF { \c_@@_props_root_tl \l_@@_property_tl } { \@@_define_key:n {#2} } { - \__msg_kernel_error:nnxx { kernel } { property-unknown } - { \l_@@_property_tl } { \l_keys_path_tl } + \str_if_eq_x:nnF { \l_@@_property_tl } { .abort: } + { + \__msg_kernel_error:nnxx { kernel } { property-unknown } + { \l_@@_property_tl } { \l_keys_path_tl } + } } } % \end{macrocode} @@ -1101,7 +1121,10 @@ \tl_set:Nx \l_keys_path_tl { \l_@@_module_tl / } \tl_if_in:nnTF {#1} { . } { \@@_property_find:w #1 \q_stop } - { \__msg_kernel_error:nnx { kernel } { key-no-property } {#1} } + { + \__msg_kernel_error:nnx { kernel } { key-no-property } {#1} + \tl_set:Nn \l_@@_property_tl { .abort: } + } } \cs_new_protected:Npn \@@_property_find:w #1 . #2 \q_stop { @@ -1148,12 +1171,12 @@ % % \subsection{Turning properties into actions} % -% \begin{macro}[int]{\@@_bool_set:NN} +% \begin{macro}[int]{\@@_bool_set:Nn, \@@_bool_set:cn} % Boolean keys are really just choices, but all done by hand. The -% second argument here is the scope: either empty or \texttt{g} for +% second argument here is the scope: either empty or \texttt{ g } for % global. % \begin{macrocode} -\cs_new:Npn \@@_bool_set:NN #1#2 +\cs_new_protected:Npn \@@_bool_set:Nn #1#2 { \bool_if_exist:NF #1 { \bool_new:N #1 } \@@_choice_make: @@ -1168,13 +1191,14 @@ } \@@_default_set:n { true } } +\cs_generate_variant:Nn \@@_bool_set:Nn { c } % \end{macrocode} % \end{macro} % -% \begin{macro}[int]{\@@_bool_set_inverse:NN} +% \begin{macro}[int]{\@@_bool_set_inverse:Nn, \@@_bool_set_inverse:cn} % Inverse boolean setting is much the same. % \begin{macrocode} -\cs_new:Npn \@@_bool_set_inverse:NN #1#2 +\cs_new_protected:Npn \@@_bool_set_inverse:Nn #1#2 { \bool_if_exist:NF #1 { \bool_new:N #1 } \@@_choice_make: @@ -1189,6 +1213,7 @@ } \@@_default_set:n { true } } +\cs_generate_variant:Nn \@@_bool_set_inverse:Nn { c } % \end{macrocode} % \end{macro} % @@ -1232,60 +1257,8 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[int]{\@@_choices_generate:n} -% \begin{macro}[aux]{\@@_choices_generate_aux:n} -% Creating multiple-choices means setting up the \enquote{indicator} -% code, then applying whatever the user wanted. -% \begin{macrocode} -\cs_new_protected:Npn \@@_choices_generate:n #1 - { - \cs_if_exist:cTF - { \c_@@_vars_root_tl \l_keys_path_tl .choice~code } - { - \@@_choice_make: - \int_zero:N \l_keys_choice_int - \clist_map_function:nN {#1} \@@_choices_generate_aux:n - } - { - \__msg_kernel_error:nnx { kernel } - { generate-choices-before-code } { \l_keys_path_tl } - } - } -\cs_new_protected:Npn \@@_choices_generate_aux:n #1 - { - \int_incr:N \l_keys_choice_int - \@@_cmd_set:nx { \l_keys_path_tl / #1 } - { - \tl_set:Nn \exp_not:N \l_keys_choice_tl {#1} - \int_set:Nn \exp_not:N \l_keys_choice_int - { \int_use:N \l_keys_choice_int } - \exp_not:v - { \c_@@_vars_root_tl \l_keys_path_tl .choice~code } - } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[int]{\@@_choice_code_store:n, \@@_choice_code_store:x} -% The code for making multiple choices is stored in a token list. -% \begin{macrocode} -\cs_new_protected:Npn \@@_choice_code_store:n #1 - { - \cs_if_exist:cF - { \c_@@_vars_root_tl \l_keys_path_tl .choice~code } - { - \tl_new:c - { \c_@@_vars_root_tl \l_keys_path_tl .choice~code } - } - \tl_set:cn { \c_@@_vars_root_tl \l_keys_path_tl .choice~code } - {#1} - } -\cs_generate_variant:Nn \@@_choice_code_store:n { x } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[int]{\@@_cmd_set:nn, \@@_cmd_set:nx, \@@_cmd_set:Vo} +% \begin{macro}[int] +% {\@@_cmd_set:nn, \@@_cmd_set:nx, \@@_cmd_set:Vn, \@@_cmd_set:Vo} % \begin{macro}[aux]{\@@_cmd_set:n} % Creating a new command means tidying up the properties and then making % the internal function which actually does the work. @@ -1295,12 +1268,7 @@ \@@_cmd_set:n {#1} \cs_set:cpn { \c_@@_code_root_tl #1 } ##1 {#2} } -\cs_new_protected:Npn \@@_cmd_set:nx #1#2 - { - \@@_cmd_set:n {#1} - \cs_set:cpx { \c_@@_code_root_tl #1 } ##1 {#2} - } -\cs_generate_variant:Nn \@@_cmd_set:nn { Vo } +\cs_generate_variant:Nn \@@_cmd_set:nn { nx , Vn , Vo } \cs_new_protected:Npn \@@_cmd_set:n #1 { \tl_clear_new:c { \c_@@_vars_root_tl #1 .default } @@ -1311,34 +1279,30 @@ % \end{macro} % \end{macro} % -% \begin{macro}[int]{\@@_default_set:n, \@@_default_set:V} +% \begin{macro}[int]{\@@_default_set:n} % Setting a default value is easy. % \begin{macrocode} \cs_new_protected:Npn \@@_default_set:n #1 { \tl_set:cn { \c_@@_vars_root_tl \l_keys_path_tl .default } {#1} } -\cs_generate_variant:Nn \@@_default_set:n { V } % \end{macrocode} % \end{macro} -% -% \begin{macro}[aux]{\@@_initialise:n, \@@_initialise:V} -% \begin{macro}[aux, EXP]{\@@_initialise:wn} +% +% \begin{macro}[int]{\@@_initialise:n} +% \begin{macro}[aux]{\@@_initialise:wn} % A set up for initialisation from which the key system requires that % the path is split up into a module and a key name. At this stage, % \cs{l_keys_path_tl} will contain \texttt{/} so a split is easy to do. % \begin{macrocode} \cs_new_protected:Npn \@@_initialise:n #1 - { - \use:x - { \exp_after:wN \@@_initialise:wn \l_keys_path_tl \q_stop {#1} } - } -\cs_generate_variant:Nn \@@_initialise:n { V } -\cs_new:Npn \@@_initialise:wn #1 / #2 \q_stop #3 - { \keys_set:nn {#1} { #2 = \exp_not:n { {#3} } } } + { \exp_after:wN \@@_initialise:wn \l_keys_path_tl \q_stop {#1} } +\cs_new_protected:Npn \@@_initialise:wn #1 / #2 \q_stop #3 + { \keys_set:nn {#1} { #2 = {#3} } } % \end{macrocode} % \end{macro} % \end{macro} % -% \begin{macro}{\@@_meta_make:n, \@@_meta_make:x} +% \begin{macro}[int]{\@@_meta_make:n} +% \begin{macro}[int]{\@@_meta_make:nn} % To create a meta-key, simply set up to pass data through. % \begin{macrocode} \cs_new_protected:Npn \@@_meta_make:n #1 @@ -1346,13 +1310,11 @@ \@@_cmd_set:Vo \l_keys_path_tl { \exp_after:wN \keys_set:nn \exp_after:wN { \l_@@_module_tl } {#1} } } -\cs_new_protected:Npn \@@_meta_make:x #1 - { - \@@_cmd_set:nx { \l_keys_path_tl } - { \exp_not:N \keys_set:nn { \l_@@_module_tl } {#1} } - } +\cs_new_protected:Npn \@@_meta_make:nn #1#2 + { \@@_cmd_set:Vn \l_keys_path_tl { \keys_set:nn {#1} {#2} } } % \end{macrocode} % \end{macro} +% \end{macro} % % \begin{macro}[int]{\@@_multichoice_find:n} % \begin{macro}[int]{\@@_multichoice_make:} @@ -1408,93 +1370,95 @@ % \end{macrocode} % \end{macro} % -% \begin{macro}[int]{\@@_variable_set:NnNN, \@@_variable_set:cnNN} -% \begin{macro}[int]{\@@_variable_set:NnN, \@@_variable_set:cnN} +% \begin{macro}[int]{\@@_variable_set:NnnN, \@@_variable_set:cnnN} % Setting a variable takes the type and scope separately so that -% it is easy to make a new variable if needed. The three-argument -% version is set up so that the use of |{ }| as an \texttt{N}-type -% variable is only done once! +% it is easy to make a new variable if needed. % \begin{macrocode} -\cs_new_protected:Npn \@@_variable_set:NnNN #1#2#3#4 +\cs_new_protected:Npn \@@_variable_set:NnnN #1#2#3#4 { \use:c { #2_if_exist:NF } #1 { \use:c { #2 _new:N } #1 } \@@_cmd_set:nx { \l_keys_path_tl } - { \exp_not:c { #2 _ #3 set:N #4 } \exp_not:N #1 {##1} } + { \exp_not:c { #2 _ #3 set:N #4 } \exp_not:N #1 \exp_not:n { {##1} } } } -\cs_new_protected:Npn \@@_variable_set:NnN #1#2#3 - { \@@_variable_set:NnNN #1 {#2} { } #3 } -\cs_generate_variant:Nn \@@_variable_set:NnNN { c } -\cs_generate_variant:Nn \@@_variable_set:NnN { c } +\cs_generate_variant:Nn \@@_variable_set:NnnN { c } % \end{macrocode} % \end{macro} -% \end{macro} % % \subsection{Creating key properties} % % The key property functions are all wrappers for internal functions, % meaning that things stay readable and can also be altered later on. -% -% \begin{macro}{.bool_set:N} -% \begin{macro}{.bool_gset:N} +% +% Importantly, while key properties have \enquote{normal} argument specs, the +% underlying code always supplies one braced argument to these. As such, argument +% expansion is handled by hand rather than using the standard tools. This shows +% up particularly for the two-argument properties, where things would otherwise +% go badly wrong. +% +% \begin{macro}{.bool_set:N, .bool_set:c} +% \begin{macro}{.bool_gset:N, .bool_gset:c} % One function for this. % \begin{macrocode} \cs_new_protected:cpn { \c_@@_props_root_tl .bool_set:N } #1 - { \@@_bool_set:NN #1 { } } + { \@@_bool_set:Nn #1 { } } +\cs_new_protected:cpn { \c_@@_props_root_tl .bool_set:c } #1 + { \@@_bool_set:cn {#1} { } } \cs_new_protected:cpn { \c_@@_props_root_tl .bool_gset:N } #1 - { \@@_bool_set:NN #1 g } + { \@@_bool_set:Nn #1 { g } } +\cs_new_protected:cpn { \c_@@_props_root_tl .bool_gset:c } #1 + { \@@_bool_set:cn {#1} { g } } % \end{macrocode} % \end{macro} % \end{macro} % -% \begin{macro}{.bool_set_inverse:N} -% \begin{macro}{.bool_gset_inverse:N} +% \begin{macro}{.bool_set_inverse:N, .bool_set_inverse:c} +% \begin{macro}{.bool_gset_inverse:N, .bool_gset_inverse:c} % One function for this. % \begin{macrocode} \cs_new_protected:cpn { \c_@@_props_root_tl .bool_set_inverse:N } #1 - { \@@_bool_set_inverse:NN #1 { } } + { \@@_bool_set_inverse:Nn #1 { } } +\cs_new_protected:cpn { \c_@@_props_root_tl .bool_set_inverse:c } #1 + { \@@_bool_set_inverse:cn {#1} { } } \cs_new_protected:cpn { \c_@@_props_root_tl .bool_gset_inverse:N } #1 - { \@@_bool_set_inverse:NN #1 g } + { \@@_bool_set_inverse:Nn #1 { g } } +\cs_new_protected:cpn { \c_@@_props_root_tl .bool_gset_inverse:c } #1 + { \@@_bool_set_inverse:cn {#1} { g } } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{.choice:} % Making a choice is handled internally, as it is also needed by -% \texttt{.generate_choices:n}. +% \texttt{.generate_choices:n}. % \begin{macrocode} \cs_new_protected_nopar:cpn { \c_@@_props_root_tl .choice: } { \@@_choice_make: } % \end{macrocode} % \end{macro} % -% \begin{macro}{.choices:nn} +% \begin{macro} +% {.choices:nn, .choices:Vn, .choices:on, .choices:xn} % For auto-generation of a series of mutually-exclusive choices. % Here, |#1| will consist of two separate % arguments, hence the slightly odd-looking implementation. % \begin{macrocode} \cs_new_protected:cpn { \c_@@_props_root_tl .choices:nn } #1 { \@@_choices_make:nn #1 } +\cs_new_protected:cpn { \c_@@_props_root_tl .choices:Vn } #1 + { \exp_args:NV \@@_choices_make:nn #1 } +\cs_new_protected:cpn { \c_@@_props_root_tl .choices:on } #1 + { \exp_args:No \@@_choices_make:nn #1 } +\cs_new_protected:cpn { \c_@@_props_root_tl .choices:xn } #1 + { \exp_args:Nx \@@_choices_make:nn #1 } % \end{macrocode} % \end{macro} % -% \begin{macro}{.code:n, .code:x} +% \begin{macro}{.code:n} % Creating code is simply a case of passing through to the underlying % \texttt{set} function. % \begin{macrocode} \cs_new_protected:cpn { \c_@@_props_root_tl .code:n } #1 { \@@_cmd_set:nn { \l_keys_path_tl } {#1} } -\cs_new_protected:cpn { \c_@@_props_root_tl .code:x } #1 - { \@@_cmd_set:nx { \l_keys_path_tl } {#1} } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{.choice_code:n, .choice_code:x} -% Storing the code for choices -% \begin{macrocode} -\cs_new_protected:cpn { \c_@@_props_root_tl .choice_code:n } #1 - { \@@_choice_code_store:n {#1} } -\cs_new_protected:cpn { \c_@@_props_root_tl .choice_code:x } #1 - { \@@_choice_code_store:x {#1} } % \end{macrocode} % \end{macro} % @@ -1502,24 +1466,28 @@ % \begin{macro}{.clist_gset:N, .clist_gset:c} % \begin{macrocode} \cs_new_protected:cpn { \c_@@_props_root_tl .clist_set:N } #1 - { \@@_variable_set:NnN #1 { clist } n } + { \@@_variable_set:NnnN #1 { clist } { } n } \cs_new_protected:cpn { \c_@@_props_root_tl .clist_set:c } #1 - { \@@_variable_set:cnN {#1} { clist } n } + { \@@_variable_set:cnnN {#1} { clist } { } n } \cs_new_protected:cpn { \c_@@_props_root_tl .clist_gset:N } #1 - { \@@_variable_set:NnNN #1 { clist } g n } + { \@@_variable_set:NnnN #1 { clist } { g } n } \cs_new_protected:cpn { \c_@@_props_root_tl .clist_gset:c } #1 - { \@@_variable_set:cnNN {#1} { clist } g n } + { \@@_variable_set:cnnN {#1} { clist } { g } n } % \end{macrocode} % \end{macro} % \end{macro} % -% \begin{macro}{.default:n, .default:V} +% \begin{macro}{.default:n, .default:V, .default:o, .default:x} % Expansion is left to the internal functions. % \begin{macrocode} \cs_new_protected:cpn { \c_@@_props_root_tl .default:n } #1 { \@@_default_set:n {#1} } \cs_new_protected:cpn { \c_@@_props_root_tl .default:V } #1 - { \@@_default_set:V #1 } + { \exp_args:NV \@@_default_set:n #1 } +\cs_new_protected:cpn { \c_@@_props_root_tl .default:o } #1 + { \exp_args:No \@@_default_set:n {#1} } +\cs_new_protected:cpn { \c_@@_props_root_tl .default:x } #1 + { \exp_args:Nx \@@_default_set:n {#1} } % \end{macrocode} % \end{macro} % @@ -1528,13 +1496,13 @@ % Setting a variable is very easy: just pass the data along. % \begin{macrocode} \cs_new_protected:cpn { \c_@@_props_root_tl .dim_set:N } #1 - { \@@_variable_set:NnN #1 { dim } n } + { \@@_variable_set:NnnN #1 { dim } { } n } \cs_new_protected:cpn { \c_@@_props_root_tl .dim_set:c } #1 - { \@@_variable_set:cnN {#1} { dim } n } + { \@@_variable_set:cnnN {#1} { dim } { } n } \cs_new_protected:cpn { \c_@@_props_root_tl .dim_gset:N } #1 - { \@@_variable_set:NnNN #1 { dim } g n } + { \@@_variable_set:NnnN #1 { dim } { g } n } \cs_new_protected:cpn { \c_@@_props_root_tl .dim_gset:c } #1 - { \@@_variable_set:cnNN {#1} { dim } g n } + { \@@_variable_set:cnnN {#1} { dim } { g } n } % \end{macrocode} % \end{macro} % \end{macro} @@ -1544,32 +1512,28 @@ % Setting a variable is very easy: just pass the data along. % \begin{macrocode} \cs_new_protected:cpn { \c_@@_props_root_tl .fp_set:N } #1 - { \@@_variable_set:NnN #1 { fp } n } + { \@@_variable_set:NnnN #1 { fp } { } n } \cs_new_protected:cpn { \c_@@_props_root_tl .fp_set:c } #1 - { \@@_variable_set:cnN {#1} { fp } n } + { \@@_variable_set:cnnN {#1} { fp } { } n } \cs_new_protected:cpn { \c_@@_props_root_tl .fp_gset:N } #1 - { \@@_variable_set:NnNN #1 { fp } g n } + { \@@_variable_set:NnnN #1 { fp } { g } n } \cs_new_protected:cpn { \c_@@_props_root_tl .fp_gset:c } #1 - { \@@_variable_set:cnNN {#1} { fp } g n } + { \@@_variable_set:cnnN {#1} { fp } { g } n } % \end{macrocode} % \end{macro} % \end{macro} % -% \begin{macro}{.generate_choices:n} -% Making choices is easy. -% \begin{macrocode} -\cs_new_protected:cpn { \c_@@_props_root_tl .generate_choices:n } #1 - { \@@_choices_generate:n {#1} } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{.initial:n, .initial:V} +% \begin{macro}{.initial:n, .initial:V, .initial:o, .initial:x} % The standard hand-off approach. % \begin{macrocode} \cs_new_protected:cpn { \c_@@_props_root_tl .initial:n } #1 { \@@_initialise:n {#1} } \cs_new_protected:cpn { \c_@@_props_root_tl .initial:V } #1 - { \@@_initialise:V #1 } + { \exp_args:NV \@@_initialise:n #1 } +\cs_new_protected:cpn { \c_@@_props_root_tl .initial:o } #1 + { \exp_args:No \@@_initialise:n {#1} } +\cs_new_protected:cpn { \c_@@_props_root_tl .initial:x } #1 + { \exp_args:Nx \@@_initialise:n {#1} } % \end{macrocode} % \end{macro} % @@ -1578,29 +1542,40 @@ % Setting a variable is very easy: just pass the data along. % \begin{macrocode} \cs_new_protected:cpn { \c_@@_props_root_tl .int_set:N } #1 - { \@@_variable_set:NnN #1 { int } n } + { \@@_variable_set:NnnN #1 { int } { } n } \cs_new_protected:cpn { \c_@@_props_root_tl .int_set:c } #1 - { \@@_variable_set:cnN {#1} { int } n } + { \@@_variable_set:cnnN {#1} { int } { } n } \cs_new_protected:cpn { \c_@@_props_root_tl .int_gset:N } #1 - { \@@_variable_set:NnNN #1 { int } g n } + { \@@_variable_set:NnnN #1 { int } { g } n } \cs_new_protected:cpn { \c_@@_props_root_tl .int_gset:c } #1 - { \@@_variable_set:cnNN {#1} { int } g n } + { \@@_variable_set:cnnN {#1} { int } { g } n } % \end{macrocode} % \end{macro} % \end{macro} % -%\begin{macro}{.meta:n, .meta:x} -% Making a meta is handled internally. +% \begin{macro}{.meta:n} +% Making a meta is handled internally. % \begin{macrocode} \cs_new_protected:cpn { \c_@@_props_root_tl .meta:n } #1 { \@@_meta_make:n {#1} } -\cs_new_protected:cpn { \c_@@_props_root_tl .meta:x } #1 - { \@@_meta_make:x {#1} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{.meta:nn} +% Meta with path: potentially lots of variants, but for the moment +% no so many defined. +% \begin{macrocode} +\cs_new_protected:cpn { \c_@@_props_root_tl .meta:nn } #1 + { \@@_meta_make:nn #1 } % \end{macrocode} % \end{macro} % % \begin{macro}{.multichoice:} -% \begin{macro}{.multichoices:nn} +% \begin{macro} +% { +% .multichoices:nn, .multichoices:Vn, .multichoices:on, +% .multichoices:xn, +% } % The same idea as \texttt{.choice:} and \texttt{.choices:nn}, but % where more than one choice is allowed. % \begin{macrocode} @@ -1608,6 +1583,12 @@ { \@@_multichoice_make: } \cs_new_protected:cpn { \c_@@_props_root_tl .multichoices:nn } #1 { \@@_multichoices_make:nn #1 } +\cs_new_protected:cpn { \c_@@_props_root_tl .multichoices:Vn } #1 + { \exp_args:NV \@@_multichoices_make:nn #1 } +\cs_new_protected:cpn { \c_@@_props_root_tl .multichoices:on } #1 + { \exp_args:No \@@_multichoices_make:nn #1 } +\cs_new_protected:cpn { \c_@@_props_root_tl .multichoices:xn } #1 + { \exp_args:Nx \@@_multichoices_make:nn #1 } % \end{macrocode} % \end{macro} % \end{macro} @@ -1617,13 +1598,13 @@ % Setting a variable is very easy: just pass the data along. % \begin{macrocode} \cs_new_protected:cpn { \c_@@_props_root_tl .skip_set:N } #1 - { \@@_variable_set:NnN #1 { skip } n } + { \@@_variable_set:NnnN #1 { skip } { } n } \cs_new_protected:cpn { \c_@@_props_root_tl .skip_set:c } #1 - { \@@_variable_set:cnN {#1} { skip } n } + { \@@_variable_set:cnnN {#1} { skip } { } n } \cs_new_protected:cpn { \c_@@_props_root_tl .skip_gset:N } #1 - { \@@_variable_set:NnNN #1 { skip } g n } + { \@@_variable_set:NnnN #1 { skip } { g } n } \cs_new_protected:cpn { \c_@@_props_root_tl .skip_gset:c } #1 - { \@@_variable_set:cnNN {#1} { skip } g n } + { \@@_variable_set:cnnN {#1} { skip } { g } n } % \end{macrocode} % \end{macro} % \end{macro} @@ -1636,21 +1617,21 @@ % Setting a variable is very easy: just pass the data along. % \begin{macrocode} \cs_new_protected:cpn { \c_@@_props_root_tl .tl_set:N } #1 - { \@@_variable_set:NnN #1 { tl } n } + { \@@_variable_set:NnnN #1 { tl } { } n } \cs_new_protected:cpn { \c_@@_props_root_tl .tl_set:c } #1 - { \@@_variable_set:cnN {#1} { tl } n } + { \@@_variable_set:cnnN {#1} { tl } { } n } \cs_new_protected:cpn { \c_@@_props_root_tl .tl_set_x:N } #1 - { \@@_variable_set:NnN #1 { tl } x } + { \@@_variable_set:NnnN #1 { tl } { } x } \cs_new_protected:cpn { \c_@@_props_root_tl .tl_set_x:c } #1 - { \@@_variable_set:cnN {#1} { tl } x } + { \@@_variable_set:cnnN {#1} { tl } { } x } \cs_new_protected:cpn { \c_@@_props_root_tl .tl_gset:N } #1 - { \@@_variable_set:NnNN #1 { tl } g n } + { \@@_variable_set:NnnN #1 { tl } { g } n } \cs_new_protected:cpn { \c_@@_props_root_tl .tl_gset:c } #1 - { \@@_variable_set:cnNN {#1} { tl } g n } + { \@@_variable_set:cnnN {#1} { tl } { g } n } \cs_new_protected:cpn { \c_@@_props_root_tl .tl_gset_x:N } #1 - { \@@_variable_set:NnNN #1 { tl } g x } + { \@@_variable_set:NnnN #1 { tl } { g } x } \cs_new_protected:cpn { \c_@@_props_root_tl .tl_gset_x:c } #1 - { \@@_variable_set:cnNN {#1} { tl } g x } + { \@@_variable_set:cnnN {#1} { tl } { g } x } % \end{macrocode} % \end{macro} % \end{macro} @@ -1706,7 +1687,7 @@ \keyval_parse:NNn \@@_set_elt:n \@@_set_elt:nn {#3} \cs_set_eq:NN \@@_execute_unknown: \@@_execute_unknown_std: \tl_set:Nn \l_@@_module_tl {#1} - \clist_set_eq:NN #4 \l_@@_unknown_clist + \cs_set_eq:NN #4 \l_@@_unknown_clist } \cs_generate_variant:Nn \keys_set_known:nnN { nV , nv , no } \cs_generate_variant:Nn \@@_set_known:nnnN { o } @@ -1805,14 +1786,14 @@ % \@@_execute_unknown_std:, % \@@_execute_unknown_alt: % } -% \begin{macro}[aux]{\@@_execute:nn} +% \begin{macro}[aux, EXP]{\@@_execute:nn} % Actually executing a key is done in two parts. First, look for the % key itself, then look for the \texttt{unknown} key with the same % path. If both of these fail, complain. % \begin{macrocode} -\cs_new_nopar:Npn \@@_execute: +\cs_new_protected_nopar:Npn \@@_execute: { \@@_execute:nn { \l_keys_path_tl } { \@@_execute_unknown: } } -\cs_new_nopar:Npn \@@_execute_unknown: +\cs_new_protected_nopar:Npn \@@_execute_unknown: { \@@_execute:nn { \l_@@_module_tl / unknown } { @@ -1821,7 +1802,7 @@ } } \cs_new_eq:NN \@@_execute_unknown_std: \@@_execute_unknown: -\cs_new_nopar:Npn \@@_execute_unknown_alt: +\cs_new_protected_nopar:Npn \@@_execute_unknown_alt: { \clist_put_right:Nx \l_@@_unknown_clist { @@ -1844,7 +1825,7 @@ % \end{macro} % \end{macro} % -% \begin{macro}[int]{\@@_choice_find:n} +% \begin{macro}[int, EXP]{\@@_choice_find:n} % Executing a choice has two parts. First, try the choice given, then % if that fails call the unknown key. That will exist, as it is created % when a choice is first made. So there is no need for any escape code. @@ -1886,7 +1867,7 @@ % \begin{macro}{\keys_show:nn} % Showing a key is just a question of using the correct name. % \begin{macrocode} -\cs_new:Npn \keys_show:nn #1#2 +\cs_new_protected:Npn \keys_show:nn #1#2 { \cs_show:c { \c_@@_code_root_tl #1 / \tl_to_str:n {#2} } } % \end{macrocode} % \end{macro} @@ -1904,20 +1885,18 @@ The~key~'#1'~takes~a~limited~number~of~values.\\ The~input~given,~'#2',~is~not~on~the~list~accepted. } -\__msg_kernel_new:nnnn { kernel } { generate-choices-before-code } - { No~code~available~to~generate~choices~for~key~'#1'. } +\__msg_kernel_new:nnnn { kernel } { key-choice-unknown } + { Key~'#1'~accepts~only~a~fixed~set~of~choices. } { - \c_msg_coding_error_text_tl - Before~using~.generate_choices:n~the~code~should~be~defined~ - with~'.choice_code:n'~or~'.choice_code:x'. + The~key~'#1'~only~accepts~predefined~values,~and~'#2'~is~not~one~of~these. } \__msg_kernel_new:nnnn { kernel } { key-no-property } { No~property~given~in~definition~of~key~'#1'. } { \c_msg_coding_error_text_tl - Inside~\keys_define:nn each~key~name - needs~a~property: \\ - ~ ~ #1 .<property> \\ + Inside~\keys_define:nn each~key~name~ + needs~a~property: \\ \\ + \iow_indent:n { #1 .<property> } \\ \\ LaTeX~did~not~find~a~'.'~to~indicate~the~start~of~a~property. } \__msg_kernel_new:nnnn { kernel } { key-unknown } @@ -1930,7 +1909,7 @@ { The~property~'#1'~requires~a~value. } { \c_msg_coding_error_text_tl - LaTeX~was~asked~to~set~property~'#2'~for~key~'#1'.\\ + LaTeX~was~asked~to~set~property~'#1'~for~key~'#2'.\\ No~value~was~given~for~the~property,~and~one~is~required. } \__msg_kernel_new:nnnn { kernel } { property-unknown } @@ -1955,6 +1934,86 @@ % \end{macrocode} % % \subsection{Deprecated functions} +% +% Deprecated on 2013-07-09. +% +% \begin{macro}[int]{\@@_choice_code_store:n, \@@_choice_code_store:x} +% The code for making multiple choices is stored in a token list. +% \begin{macrocode} +\cs_new_protected:Npn \@@_choice_code_store:n #1 + { + \cs_if_exist:cF + { \c_@@_vars_root_tl \l_keys_path_tl .choice~code } + { + \tl_new:c + { \c_@@_vars_root_tl \l_keys_path_tl .choice~code } + } + \tl_set:cn { \c_@@_vars_root_tl \l_keys_path_tl .choice~code } + {#1} + } +\cs_generate_variant:Nn \@@_choice_code_store:n { x } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{.choice_code:n, .choice_code:x} +% Storing the code for choices +% \begin{macrocode} +\cs_new_protected:cpn { \c_@@_props_root_tl .choice_code:n } #1 + { \@@_choice_code_store:n {#1} } +\cs_new_protected:cpn { \c_@@_props_root_tl .choice_code:x } #1 + { \@@_choice_code_store:x {#1} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[int]{\@@_choices_generate:n} +% \begin{macro}[aux]{\@@_choices_generate_aux:n} +% Creating multiple-choices means setting up the \enquote{indicator} +% code, then applying whatever the user wanted. +% \begin{macrocode} +\cs_new_protected:Npn \@@_choices_generate:n #1 + { + \cs_if_exist:cTF + { \c_@@_vars_root_tl \l_keys_path_tl .choice~code } + { + \@@_choice_make: + \int_zero:N \l_keys_choice_int + \clist_map_function:nN {#1} \@@_choices_generate_aux:n + } + { + \__msg_kernel_error:nnx { kernel } + { generate-choices-before-code } { \l_keys_path_tl } + } + } +\cs_new_protected:Npn \@@_choices_generate_aux:n #1 + { + \int_incr:N \l_keys_choice_int + \@@_cmd_set:nx { \l_keys_path_tl / #1 } + { + \tl_set:Nn \exp_not:N \l_keys_choice_tl {#1} + \int_set:Nn \exp_not:N \l_keys_choice_int + { \int_use:N \l_keys_choice_int } + \exp_not:v + { \c_@@_vars_root_tl \l_keys_path_tl .choice~code } + } + } +\__msg_kernel_new:nnnn { kernel } { generate-choices-before-code } + { No~code~available~to~generate~choices~for~key~'#1'. } + { + \c_msg_coding_error_text_tl + Before~using~.generate_choices:n~the~code~should~be~defined~ + with~'.choice_code:n'~or~'.choice_code:x'. + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{.generate_choices:n} +% Making choices is easy. +% \begin{macrocode} +\cs_new_protected:cpn { \c_@@_props_root_tl .generate_choices:n } #1 + { \@@_choices_generate:n {#1} } +% \end{macrocode} +% \end{macro} % % Deprecated on 2011-05-27, for removal by 2011-08-31. % @@ -1972,9 +2031,9 @@ % \end{macro} % \end{macro} % \end{macro} -% +% % Internal material for removal by 2012-12-31. -% +% % \begin{macrocode} %<*deprecated> \cs_new_eq:NN \c_keys_code_root_tl \c__keys_code_root_tl |