summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2013-07-12 22:54:42 +0000
committerKarl Berry <karl@freefriends.org>2013-07-12 22:54:42 +0000
commit60ede63177ff54dd8d1934012fbecce179a633ee (patch)
tree9dbd9e4608c9a0caa9864fedf49f0a2aea36fedf /Master/texmf-dist/source/latex/l3kernel/l3keys.dtx
parentc2d4fa6f59f3c566ccd85e3b250f0a27485bbaea (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.dtx801
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