Skip to content

Commit

Permalink
Correctly nest key filtering, etc. (fixes #526)
Browse files Browse the repository at this point in the history
  • Loading branch information
josephwright committed Jan 28, 2019
1 parent 1378ca6 commit 43fe0c7
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 65 deletions.
4 changes: 4 additions & 0 deletions l3kernel/CHANGELOG.md
Expand Up @@ -7,6 +7,10 @@ this project uses date-based 'snapshot' version identifiers.

## [Unreleased]

### Fixed

- Handling of nested key setting when filtering, _etc._ (see #526)

## [2019-01-28]

### Added
Expand Down
136 changes: 74 additions & 62 deletions l3kernel/l3keys.dtx
Expand Up @@ -2010,16 +2010,36 @@
%
% \subsection{Setting keys}
%
% \begin{macro}{\keys_set:nn, \keys_set:nV, \keys_set:nv, \keys_set:no}
% \begin{macro}
% {
% \keys_set:nn, \keys_set:nV, \keys_set:nv, \keys_set:no,
% \@@_set:nn
% }
% \begin{macro}{\@@_set:nnn, \@@_set:onn}
% A simple wrapper again.
% A simple wrapper allowing or nesting.
% \begin{macrocode}
\cs_new_protected:Npn \keys_set:nn
{ \@@_set:onn { \l_@@_module_tl } }
\cs_new_protected:Npn \keys_set:nn #1#2
{
\use:x
{
\bool_set_false:N \exp_not:N \l_@@_only_known_bool
\bool_set_false:N \exp_not:N \l_@@_filtered_bool
\bool_set_false:N \exp_not:N \l_@@_selective_bool
\@@_set:nn \exp_not:n { {#1} {#2} }
\bool_if:NT \l_@@_only_known_bool
{ \bool_set_true:N \exp_not:N \l_@@_only_known_bool }
\bool_if:NT \l_@@_filtered_bool
{ \bool_set_true:N \exp_not:N \l_@@_filtered_bool }
\bool_if:NT \l_@@_selective_bool
{ \bool_set_true:N \exp_not:N \l_@@_selective_bool }
}
}
\cs_new_protected:Npn \@@_set:nn #1#2
{ \@@_set:onn { \l_@@_module_tl } {#1} {#2} }
\cs_new_protected:Npn \@@_set:nnn #1#2#3
{
\tl_set:Nx \l_@@_module_tl { \@@_remove_spaces:n {#2} }
\keyval_parse:NNn \@@_set:n \@@_set:nn {#3}
\keyval_parse:NNn \@@_set_keyval:n \@@_set_keyval:nn {#3}
\tl_set:Nn \l_@@_module_tl {#1}
}
\cs_generate_variant:Nn \keys_set:nn { nV , nv , no }
Expand All @@ -2039,7 +2059,6 @@
% \keys_set_known:nn, \keys_set_known:nV,
% \keys_set_known:nv, \keys_set_known:no
% }
% \begin{macro}{\@@_keys_set_known:nn}
% Setting known keys simply means setting the appropriate flag, 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
Expand All @@ -2059,23 +2078,25 @@
\cs_generate_variant:Nn \@@_set_known:nnnN { o }
\cs_new_protected:Npn \keys_set_known:nn #1#2
{
\bool_if:NTF \l_@@_only_known_bool
{ \keys_set:nn }
{ \@@_set_known:nn }
{#1} {#2}
\use:x
{
\bool_set_true:N \exp_not:N \l_@@_only_known_bool
\bool_set_false:N \exp_not:N \l_@@_filtered_bool
\bool_set_false:N \exp_not:N \l_@@_selective_bool
\@@_set:nn \exp_not:n { {#1} {#2} }
\bool_if:NF \l_@@_only_known_bool
{ \bool_set_false:N \exp_not:N \l_@@_only_known_bool }
\bool_if:NT \l_@@_filtered_bool
{ \bool_set_true:N \exp_not:N \l_@@_filtered_bool }
\bool_if:NT \l_@@_selective_bool
{ \bool_set_true:N \exp_not:N \l_@@_selective_bool }
}
}
\cs_generate_variant:Nn \keys_set_known:nn { nV , nv , no }
\cs_new_protected:Npn \@@_set_known:nn #1#2
{
\bool_set_true:N \l_@@_only_known_bool
\keys_set:nn {#1} {#2}
\bool_set_false:N \l_@@_only_known_bool
}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}
% {
Expand All @@ -2088,16 +2109,13 @@
% \keys_set_filter:nnn, \keys_set_filter:nnV, \keys_set_filter:nnv,
% \keys_set_filter:nno
% }
% \begin{macro}{\@@_set_filter:nnn}
% \begin{macro}
% {
% \keys_set_groups:nnn, \keys_set_groups:nnV, \keys_set_groups:nnv,
% \keys_set_groups:nno
% }
% \begin{macro}{\@@_set_groups:nnn}
% \begin{macro}{\@@_set_selective:nnn}
% \begin{macro}{\@@_set_selective:nnnn, \@@_set_selective:onnn}
% \begin{macro}{\@@_set_selective:nn}
% The idea of setting keys in a selective manner again uses flags
% 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
Expand All @@ -2116,79 +2134,73 @@
\cs_generate_variant:Nn \@@_set_filter:nnnnN { o }
\cs_new_protected:Npn \keys_set_filter:nnn #1#2#3
{
\bool_if:NTF \l_@@_filtered_bool
{ \@@_set_selective:nnn }
{ \@@_set_filter:nnn }
{#1} {#2} {#3}
\use:x
{
\bool_set_false:N \exp_not:N \l_@@_only_known_bool
\bool_set_true:N \exp_not:N \l_@@_filtered_bool
\bool_set_true:N \exp_not:N \l_@@_selective_bool
\@@_set_selective:nnn \exp_not:n { {#1} {#2} {#3} }
\bool_if:NT \l_@@_only_known_bool
{ \bool_set_true:N \exp_not:N \l_@@_only_known_bool }
\bool_if:NF \l_@@_filtered_bool
{ \bool_set_false:N \exp_not:N \l_@@_filtered_bool }
\bool_if:NF \l_@@_selective_bool
{ \bool_set_false:N \exp_not:N \l_@@_selective_bool }
}
}
\cs_generate_variant:Nn \keys_set_filter:nnn { nnV , nnv , nno }
\cs_new_protected:Npn \@@_set_filter:nnn #1#2#3
{
\bool_set_true:N \l_@@_filtered_bool
\@@_set_selective:nnn {#1} {#2} {#3}
\bool_set_false:N \l_@@_filtered_bool
}
\cs_new_protected:Npn \keys_set_groups:nnn #1#2#3
{
\bool_if:NTF \l_@@_filtered_bool
{ \@@_set_groups:nnn }
{ \@@_set_selective:nnn }
{#1} {#2} {#3}
\use:x
{
\bool_set_false:N \exp_not:N \l_@@_only_known_bool
\bool_set_false:N \exp_not:N \l_@@_filtered_bool
\bool_set_true:N \exp_not:N \l_@@_selective_bool
\@@_set_selective:nnn \exp_not:n { {#1} {#2} {#3} }
\bool_if:NT \l_@@_only_known_bool
{ \bool_set_true:N \exp_not:N \l_@@_only_known_bool }
\bool_if:NF \l_@@_filtered_bool
{ \bool_set_true:N \exp_not:N \l_@@_filtered_bool }
\bool_if:NF \l_@@_selective_bool
{ \bool_set_false:N \exp_not:N \l_@@_selective_bool }
}
}
\cs_generate_variant:Nn \keys_set_groups:nnn { nnV , nnv , nno }
\cs_new_protected:Npn \@@_set_groups:nnn #1#2#3
{
\bool_set_false:N \l_@@_filtered_bool
\@@_set_selective:nnn {#1} {#2} {#3}
\bool_set_true:N \l_@@_filtered_bool
}
\cs_new_protected:Npn \@@_set_selective:nnn
{ \@@_set_selective:onnn \l_@@_selective_seq }
\cs_new_protected:Npn \@@_set_selective:nnnn #1#2#3#4
{
\seq_set_from_clist:Nn \l_@@_selective_seq {#3}
\bool_if:NTF \l_@@_selective_bool
{ \keys_set:nn }
{ \@@_set_selective:nn }
{#2} {#4}
\@@_set:nn {#2} {#4}
\tl_set:Nn \l_@@_selective_seq {#1}
}
\cs_generate_variant:Nn \@@_set_selective:nnnn { o }
\cs_new_protected:Npn \@@_set_selective:nn #1#2
{
\bool_set_true:N \l_@@_selective_bool
\keys_set:nn {#1} {#2}
\bool_set_false:N \l_@@_selective_bool
}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@@_set:n, \@@_set:nn}
% \begin{macro}{\@@_set_aux:nnn, \@@_set_aux:onn}
% \begin{macro}{\@@_set_keyval:n, \@@_set_keyval:nn}
% \begin{macro}{\@@_set_keyval:nnn, \@@_set_keyval:onn}
% \begin{macro}{\@@_find_key_module:w}
% \begin{macro}{\@@_set_aux:, \@@_set_selective:}
% \begin{macro}{\@@_set_selective:}
% A shared system once again. First, set the current path and add a
% default if needed. There are then checks to see if the a value is
% required or forbidden. If everything passes, move on to execute the
% code.
% \begin{macrocode}
\cs_new_protected:Npn \@@_set:n #1
\cs_new_protected:Npn \@@_set_keyval:n #1
{
\bool_set_true:N \l_@@_no_value_bool
\@@_set_aux:onn \l_@@_module_tl {#1} { }
\@@_set_keyval:onn \l_@@_module_tl {#1} { }
}
\cs_new_protected:Npn \@@_set:nn #1#2
\cs_new_protected:Npn \@@_set_keyval:nn #1#2
{
\bool_set_false:N \l_@@_no_value_bool
\@@_set_aux:onn \l_@@_module_tl {#1} {#2}
\@@_set_keyval:onn \l_@@_module_tl {#1} {#2}
}
% \end{macrocode}
% The key path here can be fully defined, after which there is a search
Expand All @@ -2197,7 +2209,7 @@
% that happens on a per-key basis, we use the stack approach to restore
% the module name without a group.
% \begin{macrocode}
\cs_new_protected:Npn \@@_set_aux:nnn #1#2#3
\cs_new_protected:Npn \@@_set_keyval:nnn #1#2#3
{
\tl_set:Nx \l_keys_path_tl
{
Expand All @@ -2213,7 +2225,7 @@
{ \@@_execute: }
\tl_set:Nn \l_@@_module_tl {#1}
}
\cs_generate_variant:Nn \@@_set_aux:nnn { o }
\cs_generate_variant:Nn \@@_set_keyval:nnn { o }
\cs_new_protected:Npn \@@_find_key_module:w #1 / #2 \q_stop
{
\tl_if_blank:nTF {#2}
Expand Down
13 changes: 13 additions & 0 deletions l3kernel/testfiles/m3keys004.lvt
Expand Up @@ -228,6 +228,19 @@
}
}

\TEST { Nesting ~ setting }
{
\OMIT
\keys_define:nn { empty-module } { }
\keys_define:nn { module }
{
key-one .code:n = { \keys_set:nn { empty-module } { key-two } }
}
\TIMO
\keys_set_known:nnN { module } { key-one } \l_tmpa_clist
\clist_show:N \l_tmpa_clist
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\OMIT
Expand Down
21 changes: 18 additions & 3 deletions l3kernel/testfiles/m3keys004.tlg
Expand Up @@ -129,15 +129,30 @@ Defining key module/key-four on line ...
"other-value"
============================================================
============================================================
TEST 7: \keys_if_exist:nnTF
TEST 7: Nesting setting
============================================================
! LaTeX3 Error: The key 'empty-module/key-two' is unknown and is being
(LaTeX3) ignored.
For immediate help type H <return>.
...
l. ... }
The module 'empty-module' does not have a key called 'empty-module/key-two'.
Check that you have spelled the key name correctly.
The comma list \l_tmpa_clist is empty
> .
<recently read> }
l. ... }
============================================================
============================================================
TEST 8: \keys_if_exist:nnTF
============================================================
TRUE
FALSE
TRUE
FALSE
============================================================
============================================================
TEST 8: \keys_if_choice_exist:nnnTF
TEST 9: \keys_if_choice_exist:nnnTF
============================================================
TRUE
FALSE
Expand All @@ -149,7 +164,7 @@ FALSE
FALSE
============================================================
============================================================
TEST 9: \keys_show:nn
TEST 10: \keys_show:nn
============================================================
The key module/key-one has the properties:
> code => \TYPE {"#1"}.
Expand Down

0 comments on commit 43fe0c7

Please sign in to comment.