summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/l3kernel/l3keys.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/l3kernel/l3keys.dtx')
-rw-r--r--macros/latex/contrib/l3kernel/l3keys.dtx161
1 files changed, 89 insertions, 72 deletions
diff --git a/macros/latex/contrib/l3kernel/l3keys.dtx b/macros/latex/contrib/l3kernel/l3keys.dtx
index 9919abfd86..54155d6d4e 100644
--- a/macros/latex/contrib/l3kernel/l3keys.dtx
+++ b/macros/latex/contrib/l3kernel/l3keys.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-01-04}
+% \date{Released 2024-01-22}
%
% \maketitle
%
@@ -109,8 +109,8 @@
% Key names may contain any tokens, as they are handled internally
% using \cs{tl_to_str:n}. As discussed in
% section~\ref{sec:l3keys:subdivision}, it is suggested that the character
-% |/| is reserved for sub-division of keys into logical
-% groups. Functions and variables are \emph{not} expanded when creating
+% |/| is reserved for sub-division of keys into different subsets.
+% Functions and variables are \emph{not} expanded when creating
% key names, and so
% \begin{verbatim}
% \tl_set:Nn \l_mymodule_tmp_tl { key }
@@ -323,9 +323,15 @@
% \begin{syntax}
% \meta{key} .groups:n = \Arg{groups}
% \end{syntax}
-% Defines \meta{key} as belonging to the \meta{groups} declared. Groups
+% Defines \meta{key} as belonging to the \meta{groups} (a
+% comma-separated list). Groups
% provide a \enquote{secondary axis} for selectively setting keys, and are
% described in Section~\ref{sec:l3keys:selective}.
+% \begin{texnote}
+% The \meta{groups} argument is turned into a string then
+% interpreted as a comma-separated list, so group names cannot
+% contain commas nor start or end with a space character.
+% \end{texnote}
% \end{function}
%
% \begin{function}[added = 2016-11-22]{.inherit:n}
@@ -334,7 +340,7 @@
% \end{syntax}
% Specifies that the \meta{key} path should inherit the keys listed
% as any of the \meta{parents} (a comma list), which can be a module
-% or a subgroup. For example, after setting
+% or a sub-division thereof. For example, after setting
% \begin{verbatim}
% \keys_define:nn { foo } { test .code:n = \tl_show:n {#1} }
% \keys_define:nn { } { bar .inherit:n = foo }
@@ -541,21 +547,21 @@
% \label{sec:l3keys:subdivision}
%
% When creating large numbers of keys, it may be desirable to divide
-% them into several sub-groups for a given module. This can be achieved
+% them into several subsets for a given module. This can be achieved
% either by adding a sub-division to the module name:
% \begin{verbatim}
-% \keys_define:nn { mymodule / subgroup }
+% \keys_define:nn { mymodule / subset }
% { key .code:n = code }
% \end{verbatim}
% or to the key name:
% \begin{verbatim}
% \keys_define:nn { mymodule }
-% { subgroup / key .code:n = code }
+% { subset / key .code:n = code }
% \end{verbatim}
% As illustrated, the best choice of token for sub-dividing keys in
% this way is |/|. This is because of the method that is
% used to represent keys internally. Both of the above code fragments
-% set the same key, which has full name \texttt{mymodule/subgroup/key}.
+% set the same key, which has full name \texttt{mymodule/subset/key}.
%
% As illustrated in the next section, this subdivision is
% particularly relevant to making multiple choices.
@@ -856,29 +862,29 @@
% groups to be made \enquote{active}, or by marking one or more groups to
% be ignored in key setting.
%
-% \begin{function}[added = 2013-07-14, updated = 2019-01-29]
+% \begin{function}[added = 2024-01-10]
% {
-% \keys_set_filter:nnn, \keys_set_filter:nnV,
-% \keys_set_filter:nnv, \keys_set_filter:nno,
-% \keys_set_filter:nnnN, \keys_set_filter:nnVN,
-% \keys_set_filter:nnvN, \keys_set_filter:nnoN,
-% \keys_set_filter:nnnnN, \keys_set_filter:nnVnN,
-% \keys_set_filter:nnvnN, \keys_set_filter:nnonN,
+% \keys_set_exclude_groups:nnn, \keys_set_exclude_groups:nnV,
+% \keys_set_exclude_groups:nnv, \keys_set_exclude_groups:nno,
+% \keys_set_exclude_groups:nnnN, \keys_set_exclude_groups:nnVN,
+% \keys_set_exclude_groups:nnvN, \keys_set_exclude_groups:nnoN,
+% \keys_set_exclude_groups:nnnnN, \keys_set_exclude_groups:nnVnN,
+% \keys_set_exclude_groups:nnvnN, \keys_set_exclude_groups:nnonN,
% }
% \begin{syntax}
-% \cs{keys_set_filter:nnn} \Arg{module} \Arg{groups} \Arg{keyval list}
-% \cs{keys_set_filter:nnnN} \Arg{module} \Arg{groups} \Arg{keyval list} \meta{tl}
-% \cs{keys_set_filter:nnnnN} \Arg{module} \Arg{groups} \Arg{keyval list} \meta{root} \meta{tl}
+% \cs{keys_set_exclude_groups:nnn} \Arg{module} \Arg{groups} \Arg{keyval list}
+% \cs{keys_set_exclude_groups:nnnN} \Arg{module} \Arg{groups} \Arg{keyval list} \meta{tl}
+% \cs{keys_set_exclude_groups:nnnnN} \Arg{module} \Arg{groups} \Arg{keyval list} \meta{root} \meta{tl}
% \end{syntax}
-% Activates key filtering in an \enquote{opt-out} sense: keys assigned to any
-% of the \meta{groups} specified are ignored. The \meta{groups} are
+% Sets keys by excluding those in the specificied \meta{groups}.
+% The \meta{groups} are
% given as a comma-separated list. Unknown keys are not assigned to any
% group and are thus always set. The key--value pairs for each
% key which is filtered out are stored in the \meta{tl} in a
% comma-separated form (\emph{i.e.}~an edited version of the \meta{keyval
-% list}). The \cs{keys_set_filter:nnn} version skips this stage.
+% list}). The \cs{keys_set_exclude_groups:nnn} version skips this stage.
%
-% Use of \cs{keys_set_filter:nnnN} can be nested, with the correct residual
+% Use of \cs{keys_set_exclude_groups:nnnN} can be nested, with the correct residual
% \meta{keyval list} returned at each stage. In the version which takes
% a \meta{root} argument, the key list is returned relative to that point
% in the key tree. In the cases without a \meta{root} argument, only
@@ -1662,7 +1668,7 @@
% \end{variable}
%
% \begin{variable}{\l_@@_selective_bool, \l_@@_filtered_bool}
-% Two flags for using key groups: one to indicate that \enquote{selective}
+% Two booleans for using key groups: one to indicate that \enquote{selective}
% setting is active, a second to specify which type (\enquote{opt-in}
% or \enquote{opt-out}).
% \begin{macrocode}
@@ -1755,6 +1761,21 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\@@_cs_undefine:c}
+% Local version of \cs{cs_undefine:c} to avoid sprinkling
+% \cs{tex_undefined:D} everywhere.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_cs_undefine:c #1
+ {
+ \if_cs_exist:w #1 \cs_end:
+ \else:
+ \use_i:nnnn
+ \fi:
+ \cs_set_eq:cN {#1} \tex_undefined:D
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \subsection{The key defining mechanism}
%
% \begin{macro}{\keys_define:nn, \keys_define:ne, \keys_define:nx}
@@ -2061,9 +2082,8 @@
{
\tl_if_empty:nTF {#1}
{
- \cs_set_eq:cN
+ \@@_cs_undefine:c
{ \c_@@_default_root_str \l_keys_path_str }
- \tex_undefined:D
}
{
\cs_set_nopar:cpe
@@ -2084,11 +2104,11 @@
% \begin{macrocode}
\cs_new_protected:Npn \@@_groups_set:n #1
{
- \clist_set:Nn \l_@@_groups_clist {#1}
+ \clist_set:Ne \l_@@_groups_clist { \tl_to_str:n {#1} }
\clist_if_empty:NTF \l_@@_groups_clist
{
- \cs_set_eq:cN { \c_@@_groups_root_str \l_keys_path_str }
- \tex_undefined:D
+ \@@_cs_undefine:c
+ { \c_@@_groups_root_str \l_keys_path_str }
}
{
\cs_set_eq:cN { \c_@@_groups_root_str \l_keys_path_str }
@@ -2222,9 +2242,8 @@
\clist_map_inline:nn
{ code , default , groups , inherit , type , check }
{
- \cs_set_eq:cN
+ \@@_cs_undefine:c
{ \tl_use:c { c_@@_ ##1 _root_str } \l_keys_path_str }
- \tex_undefined:D
}
}
% \end{macrocode}
@@ -2254,9 +2273,8 @@
{ \c_@@_check_root_str \l_keys_path_str }
{ @@_check_ #1 : }
{
- \cs_set_eq:cN
+ \@@_cs_undefine:c
{ \c_@@_check_root_str \l_keys_path_str }
- \tex_undefined:D
}
}
}
@@ -2831,7 +2849,7 @@
% \keys_set_known:no
% }
% \begin{macro}{\@@_set_known:nnn}
-% Setting known keys simply means setting the appropriate flag, then
+% Setting known keys simply means setting the appropriate boolean, then
% running the standard code. To allow for nested setting, any existing
% value of \cs{l_@@_unused_clist} is saved on the stack and reset
% afterwards. Note that for speed/simplicity reasons we use a \texttt{tl}
@@ -2853,8 +2871,8 @@
{
\clist_clear:N \l_@@_unused_clist
\@@_set_known:nnn {#2} {#3} {#4}
- \__kernel_tl_set:Ne #5 { \exp_not:o \l_@@_unused_clist }
- \__kernel_tl_set:Ne \l_@@_unused_clist { \exp_not:n {#1} }
+ \__kernel_tl_set:Nx #5 { \exp_not:o \l_@@_unused_clist }
+ \__kernel_tl_set:Nx \l_@@_unused_clist { \exp_not:n {#1} }
}
\cs_new_protected:Npn \keys_set_known:nn #1#2
{ \@@_set_known:nnn \q_@@_no_value {#1} {#2} }
@@ -2887,21 +2905,21 @@
%
% \begin{macro}
% {
-% \keys_set_filter:nnnN, \keys_set_filter:nnVN, \keys_set_filter:nnvN,
-% \keys_set_filter:nnoN
+% \keys_set_exclude_groups:nnnN, \keys_set_exclude_groups:nnVN,
+% \keys_set_exclude_groups:nnvN, \keys_set_exclude_groups:nnoN
% }
% \begin{macro}
% {
-% \keys_set_filter:nnnnN, \keys_set_filter:nnVnN,
-% \keys_set_filter:nnvnN, \keys_set_filter:nnonN
+% \keys_set_exclude_groups:nnnnN, \keys_set_exclude_groups:nnVnN,
+% \keys_set_exclude_groups:nnvnN, \keys_set_exclude_groups:nnonN
% }
-% \begin{macro}{\@@_set_filter:nnnnnN}
+% \begin{macro}{\@@_set_exclude_groups:nnnnnN}
% \begin{macro}
% {
-% \keys_set_filter:nnn, \keys_set_filter:nnV, \keys_set_filter:nnv,
-% \keys_set_filter:nno
+% \keys_set_exclude_groups:nnn, \keys_set_exclude_groups:nnV,
+% \keys_set_exclude_groups:nnv, \keys_set_exclude_groups:nno
% }
-% \begin{macro}{\@@_set_filter:nnnn}
+% \begin{macro}{\@@_set_exclude_groups:nnnn}
% \begin{macro}
% {
% \keys_set_groups:nnn, \keys_set_groups:nnV, \keys_set_groups:nnv,
@@ -2909,35 +2927,35 @@
% }
% \begin{macro}{\@@_set_selective:nnn}
% \begin{macro}{\@@_set_selective:nnnn}
-% The idea of setting keys in a selective manner again uses flags
+% The idea of setting keys in a selective manner again uses booleans
% wrapped around the basic code. The comments on \cs{keys_set_known:nnN}
% also apply here. We have a bit more shuffling to do to keep everything
% nestable.
% \begin{macrocode}
-\cs_new_protected:Npn \keys_set_filter:nnnN #1#2#3#4
+\cs_new_protected:Npn \keys_set_exclude_groups:nnnN #1#2#3#4
{
- \exp_args:No \@@_set_filter:nnnnnN
+ \exp_args:No \@@_set_exclude_groups:nnnnnN
\l_@@_unused_clist
\q_@@_no_value {#1} {#2} {#3} #4
}
-\cs_generate_variant:Nn \keys_set_filter:nnnN { nnV , nnv , nno }
-\cs_new_protected:Npn \keys_set_filter:nnnnN #1#2#3#4#5
+\cs_generate_variant:Nn \keys_set_exclude_groups:nnnN { nnV , nnv , nno }
+\cs_new_protected:Npn \keys_set_exclude_groups:nnnnN #1#2#3#4#5
{
- \exp_args:No \@@_set_filter:nnnnnN
+ \exp_args:No \@@_set_exclude_groups:nnnnnN
\l_@@_unused_clist {#4} {#1} {#2} {#3} #5
}
-\cs_generate_variant:Nn \keys_set_filter:nnnnN { nnV , nnv , nno }
-\cs_new_protected:Npn \@@_set_filter:nnnnnN #1#2#3#4#5#6
+\cs_generate_variant:Nn \keys_set_exclude_groups:nnnnN { nnV , nnv , nno }
+\cs_new_protected:Npn \@@_set_exclude_groups:nnnnnN #1#2#3#4#5#6
{
\clist_clear:N \l_@@_unused_clist
- \@@_set_filter:nnnn {#2} {#3} {#4} {#5}
- \__kernel_tl_set:Ne #6 { \exp_not:o \l_@@_unused_clist }
- \__kernel_tl_set:Ne \l_@@_unused_clist { \exp_not:n {#1} }
+ \@@_set_exclude_groups:nnnn {#2} {#3} {#4} {#5}
+ \__kernel_tl_set:Nx #6 { \exp_not:o \l_@@_unused_clist }
+ \__kernel_tl_set:Nx \l_@@_unused_clist { \exp_not:n {#1} }
}
-\cs_new_protected:Npn \keys_set_filter:nnn #1#2#3
- {\@@_set_filter:nnnn \q_@@_no_value {#1} {#2} {#3} }
-\cs_generate_variant:Nn \keys_set_filter:nnn { nnV , nnv , nno }
-\cs_new_protected:Npn \@@_set_filter:nnnn #1#2#3#4
+\cs_new_protected:Npn \keys_set_exclude_groups:nnn #1#2#3
+ {\@@_set_exclude_groups:nnnn \q_@@_no_value {#1} {#2} {#3} }
+\cs_generate_variant:Nn \keys_set_exclude_groups:nnn { nnV , nnv , nno }
+\cs_new_protected:Npn \@@_set_exclude_groups:nnnn #1#2#3#4
{
\use:e
{
@@ -2981,7 +2999,8 @@
{ \exp_args:No \@@_set_selective:nnnn \l_@@_selective_seq }
\cs_new_protected:Npn \@@_set_selective:nnnn #1#2#3#4
{
- \seq_set_from_clist:Nn \l_@@_selective_seq {#3}
+ \exp_args:NNe \seq_set_from_clist:Nn
+ \l_@@_selective_seq { \tl_to_str:n {#3} }
\@@_set:nn {#2} {#4}
\tl_set:Nn \l_@@_selective_seq {#1}
}
@@ -3044,7 +3063,7 @@
% \begin{macrocode}
\cs_new_protected:Npn \@@_set_keyval:nnn #1#2#3
{
- \__kernel_tl_set:Ne \l_keys_path_str
+ \__kernel_tl_set:Nx \l_keys_path_str
{
\tl_if_blank:nF {#1}
{ #1 / }
@@ -3118,23 +3137,21 @@
% of groups which apply to a key with the list of those which have been
% set active. That requires two mappings, and again a different outcome
% depending on whether opt-in or opt-out is set.
-% We cannot replace the clist mapping by \cs{clist_if_in:NnTF} because
-% catcodes may not be the same; they cannot be normalized easily in the
-% clist because of the remote possibility that some items need braces
-% if they involve commas or leading/trailing spaces.
+% It is safe to use \cs{clist_if_in:NnTF} because
+% both \cs{l_@@_selective_seq} and \cs{l_@@_groups_clist} contain the
+% groups as strings, without leading/trailing spaces in any item,
+% since the \pkg{l3clist} functions were applied to the result of
+% applying \cs{tl_to_str:n}.
% \begin{macrocode}
\cs_new_protected:Npn \@@_check_groups:
{
\bool_set_false:N \l_@@_tmp_bool
\seq_map_inline:Nn \l_@@_selective_seq
{
- \clist_map_inline:Nn \l_@@_groups_clist
+ \clist_if_in:NnT \l_@@_groups_clist {##1}
{
- \str_if_eq:nnT {##1} {####1}
- {
- \bool_set_true:N \l_@@_tmp_bool
- \clist_map_break:n \seq_map_break:
- }
+ \bool_set_true:N \l_@@_tmp_bool
+ \seq_map_break:
}
}
\bool_if:NTF \l_@@_tmp_bool
@@ -3325,7 +3342,7 @@
}
\cs_new_protected:Npn \@@_store_unused_aux:
{
- \__kernel_tl_set:Ne \l_@@_relative_tl
+ \__kernel_tl_set:Nx \l_@@_relative_tl
{ \exp_args:No \@@_trim_spaces:n \l_@@_relative_tl }
\use:e
{