[latex3-commits] [git/LaTeX3-latex3-latex3] key-expansion: f-type expand key names (88f3a6103)

Joseph Wright joseph.wright at morningstar2.co.uk
Thu Feb 10 23:27:52 CET 2022


Repository : https://github.com/latex3/latex3
On branch  : key-expansion
Link       : https://github.com/latex3/latex3/commit/88f3a6103a058c1b632490d1379dd3b44aa222b8

>---------------------------------------------------------------

commit 88f3a6103a058c1b632490d1379dd3b44aa222b8
Author: Joseph Wright <joseph.wright at morningstar2.co.uk>
Date:   Thu Feb 10 19:01:27 2022 +0000

    f-type expand key names


>---------------------------------------------------------------

88f3a6103a058c1b632490d1379dd3b44aa222b8
 l3kernel/CHANGELOG.md              |   3 +
 l3kernel/l3keys.dtx                | 257 ++++++++++++++++++++++---------------
 l3kernel/testfiles/m3keys001.lvt   |   7 -
 l3kernel/testfiles/m3keys001.tlg   |   6 -
 l3kernel/testfiles/m3keyval001.tlg |  18 +++
 l3kernel/testfiles/m3prop005.lvt   |  18 +--
 l3kernel/testfiles/m3prop005.tlg   |  22 ++--
 7 files changed, 197 insertions(+), 134 deletions(-)

diff --git a/l3kernel/CHANGELOG.md b/l3kernel/CHANGELOG.md
index fe785d688..004865da7 100644
--- a/l3kernel/CHANGELOG.md
+++ b/l3kernel/CHANGELOG.md
@@ -7,6 +7,9 @@ this project uses date-based 'snapshot' version identifiers.
 
 ## [Unreleased]
 
+### Changed
+- Expand key names using `f`-type expansion
+
 ## [2022-02-05]
 
 ### Added
diff --git a/l3kernel/l3keys.dtx b/l3kernel/l3keys.dtx
index 087bbf411..a092b8bec 100644
--- a/l3kernel/l3keys.dtx
+++ b/l3kernel/l3keys.dtx
@@ -102,21 +102,10 @@
 %     }
 % \end{verbatim}
 %
-% Key names may contain any tokens, as they are handled internally
-% using \cs{tl_to_str:n}. As discussed in
+% 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
-% key names, and so
-% \begin{verbatim}
-%   \tl_set:Nn \l_mymodule_tmp_tl { key }
-%   \keys_define:nn { mymodule }
-%     {
-%       \l_mymodule_tmp_tl .code:n = code
-%     }
-% \end{verbatim}
-% creates a key called |\l_mymodule_tmp_tl|, and not one called
-% \texttt{key}.
+% groups.
 %
 % \section{Creating keys}
 %
@@ -953,9 +942,10 @@
 % \begin{verbatim}
 %   key = value here,
 % \end{verbatim}
-% are treated identically.
+% are treated identically. Key \emph{names} are subject to expansion such that
+% they must start with a non-expandable non-space token.
 %
-% \begin{function}[rEXP, added=2020-12-19, updated = 2021-05-10]{\keyval_parse:nnn}
+% \begin{function}[rEXP, added=2020-12-19, updated = 2022-02-10]{\keyval_parse:nnn}
 %   \begin{syntax}
 %     \cs{keyval_parse:nnn} \Arg{code_1} \Arg{code_2} \Arg{key--value list}
 %   \end{syntax}
@@ -993,7 +983,7 @@
 %   \end{texnote}
 % \end{function}
 %
-% \begin{function}[rEXP, updated = 2021-05-10]{\keyval_parse:NNn}
+% \begin{function}[rEXP, updated = 2022-02-10]{\keyval_parse:NNn}
 %   \begin{syntax}
 %     \cs{keyval_parse:NNn} \meta{function_1} \meta{function_2} \Arg{key--value list}
 %   \end{syntax}
@@ -1075,6 +1065,90 @@
 %    \end{macrocode}
 % \end{variable}
 %
+% \begin{macro}[EXP]{\keyval_parse:nnn, \keyval_parse:NNn}
+%   The main function starts the loop: there is only one outer loop although
+%   there is additional processing. The use of \cs{s_@@_mark} here prevents
+%   loss of braces from the key argument.
+%    \begin{macrocode}
+\cs_if_exist:NTF \tex_expanded:D
+  {
+    \cs_new:Npn \keyval_parse:nnn #1#2#3
+      {
+        \__kernel_exp_not:w \tex_expanded:D
+          {
+            {
+              \@@_loop:Nw \s_@@_mark #3
+                , \s_@@_tail , {#1} {#2}
+            }
+          }
+     }
+  }
+  {
+    \cs_new:Npn \keyval_parse:nnn #1#2#3
+      {
+        \group_align_safe_begin:
+        \@@_loop:w \s_@@_mark #3
+          , \s_@@_tail , {#1} {#2}
+        \group_align_safe_end:
+      }
+  }
+\cs_new_eq:NN \keyval_parse:NNn \keyval_parse:nnn
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_loop:w, \@@_loop_space:w}
+% \begin{macro}[EXP]{\@@_loop_space:Nw}
+%   Before expansion, we need to remove any leading spaces: we have to
+%   ensure that the \texttt{f}-type expansion will expand the first
+%   non-space. We use a private copy of the \cs{tl_if_head_is_space:n(TF)}
+%   code.
+%    \begin{macrocode}
+\cs_new:Npn \@@_loop:w #1 \s_@@_tail ,
+  {
+    \if:w
+      \if_false: { \fi:
+        \exp_after:wN \@@_loop_space:w
+          \exp_after:wN \prg_do_nothing: \use_none:n #1 ? ~
+      }
+      \scan_stop: \scan_stop:
+      \exp_after:wN \@@_loop_space:Nw
+    \else:
+      \exp_after:wN \@@_loop:Nw
+    \fi:
+    #1 \s_@@_tail ,
+  }
+\cs_new:Npn \@@_loop_space:w #1 ~
+  {
+    \if:w \scan_stop: \__kernel_tl_to_str:w \exp_after:wN {#1} \scan_stop:
+    \else:
+      f
+    \fi:
+    \exp_after:wN \use_none:n \exp_after:wN { \if_false: } \fi:
+  }
+\use:n { \cs_new:Npn \@@_loop_space:Nw \s_@@_mark } ~
+  { \@@_loop:w \s_@@_mark }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_loop:Nw}
+%   The next step of the loop here uses a trick. We need to be able to expand the
+%   key but \emph{not} the value. To do that we need to \texttt{f}-type expand
+%   the input. However, we do not want to expand active characters, most
+%   importantly those set up by \pkg{inputenc}. That can be achieved by using
+%   a bit of trickery: we use \cs{cs:w} so that the \texttt{f}-type expansion
+%   is \enquote{inside} a \texttt{c}-type one, but arrange that the result is
+%   actually used after the control sequence. That matches with the use of
+%   \tn{ifincsname} inside the UTF-8 setup.
+%    \begin{macrocode}
+\cs_new:Npn \@@_loop:Nw #1
+  {
+    \cs:w @@_loop_aux:w \exp_after:wN \cs_end:
+    \exp_after:wN #1 \exp:w \exp_end_continue_f:w
+  }
+%    \end{macrocode}
+% \end{macro}
+%
 %   This temporary macro will be used since some of the definitions will need an
 %   active comma or equals sign. Inside of this macro |#1| will be the active
 %   comma and |#2| will be the active equals sign.
@@ -1084,58 +1158,63 @@
     {
 %    \end{macrocode}
 %
-% \begin{macro}[EXP]{\keyval_parse:nnn, \keyval_parse:NNn}
-%   The main function starts the first of two loops. The outer loop splits the
-%   key--value list at active commas, the inner loop will do so at other commas.
-%   The use of \cs{s_@@_mark} here prevents loss of braces from the key
-%   argument.
+% \begin{macro}[EXP]{\@@_loop_aux:w, \@@_loop_active:w}
+% \begin{macro}[EXP]{\@@_loop_active:nw}
+% \begin{macro}[EXP]{\@@_loop_active:nn}
+%   Before we can deal with finding an entry, we need to remove any catcode
+%   $13$ commas in the input. That is handled by an inner loop, set up such
+%   that we do keep the total number of commas the same.
 %    \begin{macrocode}
-      \cs_if_exist:NTF \tex_expanded:D
+      \cs_new:Npn \@@_loop_aux:w ##1 \s_@@_tail ,
         {
-          \cs_new:Npn \keyval_parse:nnn ##1 ##2 ##3
-            {
-              \__kernel_exp_not:w \tex_expanded:D
-                {
-                  {
-                    \@@_loop_active:nnw {##1} {##2}
-                      \s_@@_mark ##3 #1 \s_@@_tail #1
-                  }
-                }
-            }
+           \@@_loop_active:w ##1
+           #1 \s_@@_tail #1
+           \s_@@_tail ,
         }
+      \cs_new:Npn \@@_loop_active:w ##1 #1
+        { \@@_loop_active:nw {##1} }
+      \cs_new:Npn \@@_loop_active:nw ##1##2 #1
         {
-          \cs_new:Npn \keyval_parse:nnn ##1 ##2 ##3
-            {
-              \group_align_safe_begin:
-              \@@_loop_active:nnw {##1} {##2}
-                \s_@@_mark ##3 #1 \s_@@_tail #1
-              \group_align_safe_end:
-            }
+          \@@_if_recursion_tail:w ##1##2
+          \@@_end_loop_active:w \s_@@_tail
+          \@@_loop_active:nn {##1} {##2}
         }
-      \cs_new_eq:NN \keyval_parse:NNn \keyval_parse:nnn
+      \cs_new:Npn \@@_loop_active:nn ##1##2
+        { \@@_loop_active:nw { ##1 , ##2 } }
 %    \end{macrocode}
 % \end{macro}
+% \end{macro}
+% \end{macro}
 %
-% \begin{macro}[EXP]{\@@_loop_active:nnw}
-%   First a fast test for the end of the loop is done, it'll gobble everything
-%   up to a \cs{s_@@_tail}. The loop ending macro will gobble everything to the
-%   last comma in this definition.
-%   If the end isn't reached yet, start the second loop splitting at other
-%   commas, the next iteration of this first loop will be inserted by the end of
-%   \cs{@@_loop_other:nnw}.
-%    \begin{macrocode}
-      \cs_new:Npn \@@_loop_active:nnw ##1 ##2 ##3 #1
+% \begin{macro}[EXP]{\@@_loop_other:w}
+% \begin{macro}[EXP]{\@@_loop_other:nnw}
+%   After a bit of argument shuffling, the main loop uses a fast test for the
+%   end, next it splits at the first active equals sign using
+%   \cs{@@_split_active:w}.  The \cs{s_@@_nil} prevents accidental brace
+%   stripping and acts as a delimiter in the next steps. First testing for
+%   an active equals sign will reduce the%   number of necessary expansion
+%   steps for the expected average use case of other equals signs and hence
+%   perform better on average.
+%    \begin{macrocode}
+      \cs_new:Npn \@@_loop_other:w ##1 \s_@@_tail , ##2##3
+        { \@@_loop_other:nnw {##2} {##3} ##1 \s_@@_tail , }
+      \cs_new:Npn \@@_loop_other:nnw ##1##2##3 ,
         {
           \@@_if_recursion_tail:w ##3
-            \@@_end_loop_active:w \s_@@_tail
-          \@@_loop_other:nnw {##1} {##2} ##3 , \s_@@_tail ,
+            \@@_end_loop_other:w \s_@@_tail
+          \@@_split_active:w ##3 \s_@@_nil
+            \s_@@_mark \@@_split_active_auxi:w
+            #2 \s_@@_mark \@@_clean_up_active:w
+          {##1} {##2}
+          \s_@@_mark
         }
 %    \end{macrocode}
 % \end{macro}
+% \end{macro}
 %
 % \begin{macro}[EXP]{\@@_split_other:w, \@@_split_active:w}
-%   These two macros allow to split at the first equals sign of category 12 or
-%   13. At the same time they also execute branching by inserting the first
+%   These two macros allow to split at the first equals sign of category $12$ or
+%   $13$. At the same time they also execute branching by inserting the first
 %   token following \cs{s_@@_mark} that followed the equals sign. Hence they
 %   also test for the presence of such an equals sign simultaneously.
 %    \begin{macrocode}
@@ -1146,27 +1225,6 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[EXP]{\@@_loop_other:nnw}
-%   The second loop uses the same test for its end as the first loop, next it
-%   splits at the first active equals sign using \cs{@@_split_active:w}.  The
-%   \cs{s_@@_nil} prevents accidental brace stripping and acts as a delimiter in
-%   the next steps. First testing for an active equals sign will reduce the
-%   number of necessary expansion steps for the expected average use case of
-%   other equals signs and hence perform better on average.
-%    \begin{macrocode}
-      \cs_new:Npn \@@_loop_other:nnw ##1 ##2 ##3 ,
-        {
-          \@@_if_recursion_tail:w ##3
-            \@@_end_loop_other:w \s_@@_tail
-          \@@_split_active:w ##3 \s_@@_nil
-            \s_@@_mark \@@_split_active_auxi:w
-            #2 \s_@@_mark \@@_clean_up_active:w
-          {##1} {##2}
-          \s_@@_mark
-        }
-%    \end{macrocode}
-% \end{macro}
-%
 % \begin{macro}[EXP]{\@@_split_active_auxi:w}
 % \begin{macro}[EXP]{\@@_split_active_auxii:w}
 % \begin{macro}[EXP]{\@@_split_active_auxiii:w}
@@ -1332,27 +1390,6 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}[EXP]{\@@_end_loop_other:w, \@@_end_loop_active:w}
-%   All that's left for the parsing loops are the macros which end the
-%   recursion. Both just gobble the remaining tokens of the respective loop
-%   including the next recursion call. \cs{@@_end_loop_other:w} also has to
-%   insert the next iteration of the active loop.
-%    \begin{macrocode}
-      \cs_new:Npn \@@_end_loop_other:w
-          \s_@@_tail
-          \@@_split_active:w
-          \s_@@_mark \s_@@_tail
-          \s_@@_nil \s_@@_mark
-          \@@_split_active_auxi:w
-          #2 \s_@@_mark \@@_clean_up_active:w
-        { \@@_loop_active:nnw }
-      \cs_new:Npn \@@_end_loop_active:w
-          \s_@@_tail
-          \@@_loop_other:nnw ##1 \s_@@_mark \s_@@_tail , \s_@@_tail ,
-        { }
-%    \end{macrocode}
-% \end{macro}
-%
 % The parsing loops are done, so here ends the definition of \cs{@@_tmp:w},
 % which will finally set up the macros.
 %    \begin{macrocode}
@@ -1363,12 +1400,25 @@
 \group_end:
 %    \end{macrocode}
 %
+% \begin{macro}[EXP]{\@@_end_loop_other:w, \@@_end_loop_active:w}
+%   Fast methods to clean up the two comma search loops.
+%    \begin{macrocode}
+\cs_new:Npn \@@_end_loop_other:w
+  #1 \@@_clean_up_active:w #2#3 \s_@@_mark
+  { }
+\cs_new:Npn \@@_end_loop_active:w
+  \s_@@_tail \@@_loop_active:nn #1#2
+  { \@@_loop_other:w #1 }
+%    \end{macrocode}
+% \end{macro}
+%
 % \begin{macro}[EXP]{\@@_pair:nnnn, \@@_key:nn}
+% \begin{macro}[EXP]{\@@_loop_next:nnw}
 %   These macros will be called on the parsed keys and values of the key--value
 %   list. All arguments are completely trimmed. They test for blank key names
 %   and call the functions passed to \cs{keyval_parse:nnn} inside of
 %   \cs{exp_not:n} with the correct arguments. Afterwards they insert the next
-%   iteration of the other loop.
+%   iteration of the other loop, with a rearrangement.
 %    \begin{macrocode}
 \group_begin:
   \cs_set_protected:Npn \@@_tmp:w #1#2
@@ -1380,7 +1430,7 @@
           #1
           \exp_not:n { ##4 {##2} {##1} }
           #2
-          \@@_loop_other:nnw {##3} {##4}
+          \@@_loop_next:nnw {##3} {##4}
         }
       \cs_new:Npn \@@_key:nn ##1 ##2
         {
@@ -1389,15 +1439,20 @@
           #1
           \exp_not:n { ##2 {##1} }
           #2
-          \@@_loop_other:nnw {##2}
+          \@@_loop_next:nnw {##2}
         }
     }
   \cs_if_exist:NTF \tex_expanded:D
     { \@@_tmp:w { } { } }
     { \@@_tmp:w \group_align_safe_end: \group_align_safe_begin: }
 \group_end:
+\cs_new:Npn \@@_loop_next:nnw #1#2#3 \s_@@_tail ,
+  {
+    \@@_loop:w #3 \s_@@_tail , {#1} {#2}
+  }
 %    \end{macrocode}
 % \end{macro}
+% \end{macro}
 %
 % \begin{macro}[EXP]{\@@_if_empty:w,\@@_if_blank:w,\@@_if_recursion_tail:w}
 %   All these tests work by gobbling tokens until a certain combination is met,
@@ -1416,13 +1471,13 @@
 %   execute the branching.
 %    \begin{macrocode}
 \cs_new:Npn \@@_blank_true:w \s_@@_mark \s_@@_stop \@@_trim:nN #1 \@@_key:nn
-  { \@@_loop_other:nnw }
-\cs_new:Npn \@@_blank_key_error:w \s_@@_mark \s_@@_stop #1 \@@_loop_other:nnw
+  { \@@_loop_next:nnw }
+\cs_new:Npn \@@_blank_key_error:w \s_@@_mark \s_@@_stop #1 \@@_loop_next:nnw
   {
     \bool_if:NTF \l__kernel_keyval_allow_blank_keys_bool
       { #1 }
       { \msg_expandable_error:nn { keyval } { blank-key-name } }
-    \@@_loop_other:nnw
+    \@@_loop_next:nnw
   }
 %    \end{macrocode}
 % \end{macro}
diff --git a/l3kernel/testfiles/m3keys001.lvt b/l3kernel/testfiles/m3keys001.lvt
index 5d44fa04d..da68ea456 100644
--- a/l3kernel/testfiles/m3keys001.lvt
+++ b/l3kernel/testfiles/m3keys001.lvt
@@ -309,11 +309,4 @@
     \keys_set:nn { } { key.name, key.space }
   }
 
-\TEST { Spaces~after~detokenization }
-  {
-    \keys_define:nn { module } 
-      { \test .code:n = \TYPE { You~typed~"#1" } }
-    \keys_set:nn { module } { \test = Hello~World! }
-  }
-
 \END
diff --git a/l3kernel/testfiles/m3keys001.tlg b/l3kernel/testfiles/m3keys001.tlg
index 87ed9889d..75120ede4 100644
--- a/l3kernel/testfiles/m3keys001.tlg
+++ b/l3kernel/testfiles/m3keys001.tlg
@@ -166,9 +166,3 @@ l. ...  }
 <recently read> }
 l. ...  }
 ============================================================
-============================================================
-TEST 13: Spaces after detokenization
-============================================================
-Defining key module/\test on line ...
-You typed "Hello World!"
-============================================================
diff --git a/l3kernel/testfiles/m3keyval001.tlg b/l3kernel/testfiles/m3keyval001.tlg
index bd756b2fe..8762d315a 100644
--- a/l3kernel/testfiles/m3keyval001.tlg
+++ b/l3kernel/testfiles/m3keyval001.tlg
@@ -29,11 +29,29 @@ KEY: "c" VAL: " 3 "
 KEY: "d" VAL: " 4 "
 KEY: "e" VAL: "{5}"
 KEY: "f" VAL: "{6}"
+! Undefined control sequence.
+<argument> ,
+            a={1},b={2},,c={3},d={4},,e={{5}}
+l. ...}
+The control sequence at the end of the top line
+of your error message was never \def'ed. If you have
+misspelled it (e.g., `\hobx'), type `I' and the correct
+spelling (e.g., `I\hbox'). Otherwise just continue,
+and I'll forget about whatever was undefined.
 KEY: "a" VAL: "1"
 KEY: "b" VAL: "2"
 KEY: "c" VAL: "3"
 KEY: "d" VAL: "4"
 KEY: "e" VAL: "{5}"
+! Undefined control sequence.
+<argument> ,
+             , a ={ 1 }, b = { 2 }, ,, c ={ 3 } , d = { 4 } , , ,, e ={{5}},...
+l. ...}
+The control sequence at the end of the top line
+of your error message was never \def'ed. If you have
+misspelled it (e.g., `\hobx'), type `I' and the correct
+spelling (e.g., `I\hbox'). Otherwise just continue,
+and I'll forget about whatever was undefined.
 KEY: "a" VAL: " 1 "
 KEY: "b" VAL: " 2 "
 KEY: "c" VAL: " 3 "
diff --git a/l3kernel/testfiles/m3prop005.lvt b/l3kernel/testfiles/m3prop005.lvt
index 88c099cb2..e66aa0245 100644
--- a/l3kernel/testfiles/m3prop005.lvt
+++ b/l3kernel/testfiles/m3prop005.lvt
@@ -22,13 +22,13 @@
 \TEST { prop~from_keyval }
   {
     \prop_set_from_keyval:Nn \l_tmpa_prop
-      { \a = b , ~ \c ~ = ~ { ~ \d = e ~ } , , = , { = } = , ~ { } ~ = { , } , }
+      { a = b , ~ c ~ = ~ { ~ d = e ~ } , , = , { = } = , ~ { } ~ = { , } , }
     \prop_log:N \l_tmpa_prop
     \prop_gset_from_keyval:Nn \g_tmpa_prop
-      { \a = b , ~ \c ~ = ~ { ~ \d = e ~ } , , = , { = } = , ~ { } ~ = { , } , }
+      { a = b , ~ c ~ = ~ { ~ d = e ~ } , , = , { = } = , ~ { } ~ = { , } , }
     \prop_log:N \g_tmpa_prop
     \prop_const_from_keyval:Nn \c_A_prop
-      { \a = b , ~ \c ~ = ~ { ~ \d = e ~ } , , = , { = } = , ~ { } ~ = { , } , ~ {\a} = Z }
+      { a = b , ~ c ~ = ~ { ~ d = e ~ } , , = , { = } = , ~ { } ~ = { , } , ~ {a} = Z }
     \prop_log:N \c_A_prop
   }
 
@@ -48,13 +48,13 @@
 \TEST { prop_concat }
   {
     \prop_set_from_keyval:Nn \l_tmpa_prop
-      { \a = b , ~ \c ~ = ~ { ~ \d = e ~ } , , = , { = } = , ~ { } ~ = { , } , }
+      { a = b , ~ c ~ = ~ { ~ d = e ~ } , , = , { = } = , ~ { } ~ = { , } , }
     \prop_set_eq:NN \l_tmpb_prop \l_tmpa_prop
     \prop_concat:NNN \l_tmpa_prop \l_tmpa_prop \l_tmpa_prop
     \tl_if_eq:NNTF \l_tmpa_prop \l_tmpb_prop { \TRUE } { \ERROR }
     %
     \prop_gset_from_keyval:Nn \g_tmpa_prop
-      { x = y , , \a = c , ~ \c ~ = ~ { ~ \D = E ~ } , , = ? , }
+      { x = y , , a = c , ~ c ~ = ~ { ~ D = E ~ } , , = ? , }
     \prop_gconcat:ccc { g_tmpa_prop } { l_tmpa_prop } { g_tmpa_prop }
     \prop_log:N \g_tmpa_prop
   }
@@ -63,13 +63,13 @@
   {
     \group_begin:
       \prop_gset_from_keyval:Nn \g_tmpa_prop
-        { = , \a = b , ~ {\a} ~ = c , ~ \c ~ = ~ { ~ \d = e ~ } }
+        { = , a = b , ~ {a} ~ = c , ~ c ~ = ~ { ~ d = e ~ } }
       \prop_gput_from_keyval:cn { g_tmpa_prop }
-        { {~\a} = ~ c ~ , \c = ~ { }~ , ~ {\c} = {=} }
+        { {~a} = ~ c ~ , c = ~ { }~ , ~ {c} = {=} }
       \prop_set_from_keyval:Nn \l_tmpa_prop
-        { = , \a = b , ~ {\a} ~ = c , ~ \c ~ = ~ { ~ \d = e ~ } }
+        { = , a = b , ~ {a} ~ = c , ~ c ~ = ~ { ~ d = e ~ } }
       \prop_put_from_keyval:cn { l_tmpa_prop }
-        { {~\a} = ~ c ~ , \c = ~ { }~ , ~ {\c} = {=} }
+        { {~a} = ~ c ~ , c = ~ { }~ , ~ {c} = {=} }
       \tl_if_eq:NNTF \l_tmpa_prop \g_tmpa_prop { \TRUE } { \ERROR }
     \group_end:
     \prop_log:N \g_tmpa_prop
diff --git a/l3kernel/testfiles/m3prop005.tlg b/l3kernel/testfiles/m3prop005.tlg
index e70e03516..dee447949 100644
--- a/l3kernel/testfiles/m3prop005.tlg
+++ b/l3kernel/testfiles/m3prop005.tlg
@@ -5,19 +5,19 @@ Author: Bruno Le Floch
 TEST 1: prop from_keyval
 ============================================================
 The property list \l_tmpa_prop contains the pairs (without outer braces):
->  {\a }  =>  {b}
->  {\c }  =>  { \d =e }
+>  {a}  =>  {b}
+>  {c}  =>  { d=e }
 >  {}  =>  {,}
 >  {=}  =>  {}.
 The property list \g_tmpa_prop contains the pairs (without outer braces):
->  {\a }  =>  {b}
->  {\c }  =>  { \d =e }
+>  {a}  =>  {b}
+>  {c}  =>  { d=e }
 >  {}  =>  {,}
 >  {=}  =>  {}.
 Defining \c_A_prop on line ...
 The property list \c_A_prop contains the pairs (without outer braces):
->  {\a }  =>  {Z}
->  {\c }  =>  { \d =e }
+>  {a}  =>  {Z}
+>  {c}  =>  { d=e }
 >  {}  =>  {,}
 >  {=}  =>  {}.
 ============================================================
@@ -127,8 +127,8 @@ TEST 3: prop_concat
 ============================================================
 TRUE
 The property list \g_tmpa_prop contains the pairs (without outer braces):
->  {\a }  =>  {c}
->  {\c }  =>  { \D =E }
+>  {a}  =>  {c}
+>  {c}  =>  { D=E }
 >  {}  =>  {?}
 >  {=}  =>  {}
 >  {x}  =>  {y}.
@@ -139,9 +139,9 @@ TEST 4: prop_put_from_keyval
 TRUE
 The property list \g_tmpa_prop contains the pairs (without outer braces):
 >  {}  =>  {}
->  {\a }  =>  {c}
->  {\c }  =>  {=}
->  { \a }  =>  {c}.
+>  {a}  =>  {c}
+>  {c}  =>  {=}
+>  { a}  =>  {c}.
 The property list \l_tmpa_prop is empty
 > .
 ============================================================





More information about the latex3-commits mailing list.