diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3prop.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3prop.dtx | 339 |
1 files changed, 167 insertions, 172 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx index d8bec5ee50d..3046ae59e8b 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -%% File: l3prop.dtx Copyright (C) 1990-2012 The LaTeX3 Project +%% File: l3prop.dtx Copyright (C) 1990-2013 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of the %% LaTeX Project Public License (LPPL), either version 1.3c of this @@ -35,7 +35,7 @@ % %<*driver|package> \RequirePackage{l3bootstrap} -\GetIdInfo$Id: l3prop.dtx 4212 2012-09-09 12:24:04Z bruno $ +\GetIdInfo$Id: l3prop.dtx 4423 2013-01-09 00:05:30Z bruno $ {L3 Property lists} %</driver|package> %<*driver> @@ -245,7 +245,7 @@ % check that the \meta{property list} really is a property list variable. % \end{function} % -% \begin{function}[EXP,pTF]{\prop_if_empty:N, \prop_if_empty:c} +% \begin{function}[EXP, pTF]{\prop_if_empty:N, \prop_if_empty:c} % \begin{syntax} % \cs{prop_if_empty_p:N} \meta{property list} % \cs{prop_if_empty:NTF} \meta{property list} \Arg{true code} \Arg{false code} @@ -331,7 +331,7 @@ % % \section{Mapping to property lists} % -% \begin{function}[updated = 2012-06-29, rEXP] +% \begin{function}[updated = 2013-01-08, rEXP] % {\prop_map_function:NN, \prop_map_function:cN} % \begin{syntax} % \cs{prop_map_function:NN} \meta{property list} \meta{function} @@ -343,7 +343,7 @@ % should not be relied upon. % \end{function} % -% \begin{function}[updated = 2012-06-29] +% \begin{function}[updated = 2013-01-08] % {\prop_map_inline:Nn, \prop_map_inline:cn} % \begin{syntax} % \cs{prop_map_inline:Nn} \meta{property list} \Arg{inline function} @@ -432,29 +432,39 @@ % % \section{Internal property list functions} % -% \begin{variable}{\q__prop} -% The internal token used to separate out property list entries, separating -% both the \meta{key} from the \meta{value} and also one entry from another. +% \begin{variable}{\s__prop} +% The internal token used to separate out property list entries, +% surrounding each \meta{key}. % \end{variable} % -% \begin{function}{\__prop_split:NnTF} +% \begin{variable}{\l__prop_internal_tl} +% Token list used to store new key--value pairs to be inserted by +% functions of the \cs{prop_put:Nnn} family. +% \end{variable} +% +% \begin{function}[updated = 2013-01-08]{\__prop_split:NnTF} % \begin{syntax} % \cs{__prop_split:NnTF} \meta{property list} \Arg{key} \Arg{true code} \Arg{false code} % \end{syntax} % Splits the \meta{property list} at the \meta{key}, giving three -% groups: the \meta{extract} of \meta{property list} before the +% token lists: the \meta{extract} of \meta{property list} before the % \meta{key}, the \meta{value} associated with the \meta{key} and the % \meta{extract} of the \meta{property list} after the \meta{value}. -% The first \meta{extract} retains the internal structure of a property -% list. The second is only missing the leading separator \cs{q__prop}. -% This ensures that the concatenation of the two \meta{extracts} is a +% Both \meta{extracts} retain the internal structure of a property +% list, and the concatenation of the two \meta{extracts} is a % property list. % If the \meta{key} is present in the \meta{property list} then the -% \meta{true code} is left in the input stream, followed by the three -% groups: thus the \meta{true code} should properly absorb three arguments. +% \meta{true code} is left in the input stream, with |#1|, |#2|, and +% |#3| replaced by the first \meta{extract}, the \meta{value}, and the +% second extract. % If the \meta{key} is not present in the \meta{property list} then % the \meta{false code} is left in the input stream, with no trailing % material. +% Both \meta{true code} and \meta{false code} are used in the +% replacement text of a macro defined internally, hence macro +% parameter characters should be doubled, except |#1|, |#2|, and |#3| +% which stand in the \meta{true code} for the three extracts from the +% property list. % The \meta{key} comparison takes place as described for \cs{str_if_eq:nn}. % \end{function} % @@ -484,47 +494,51 @@ % % A property list is a macro whose top-level expansion is for the form % \begin{quote} -% \cs{q_@@} \meta{key_1} \cs{q_@@} \Arg{value_1} \\ +% \cs{s_@@} \meta{key_1} \cs{s_@@} \Arg{value_1} \\ % \ldots{} \\ -% \cs{q_@@} \meta{key_n} \cs{q_@@} \Arg{value_n} \\ -% \cs{q_@@} +% \cs{s_@@} \meta{key_n} \cs{s_@@} \Arg{value_n} \\ % \end{quote} -% where the trailing \cs{q_@@} is always present for performance -% reasons: this means that empty property lists are not actually empty. % -% \begin{macro}[int]{\q_@@} -% A private quark is used as a marker between entries. +% \begin{macro}[int]{\s_@@} +% A private scan mark is used as a marker surrounding each key. % \begin{macrocode} -\quark_new:N \q_@@ +\__scan_new:N \s_@@ % \end{macrocode} % \end{macro} % +% \begin{variable}{\l_@@_internal_tl} +% Token list used to store the new key--value pair inserted by +% \cs{prop_put:Nnn} and friends. +% \begin{macrocode} +\tl_new:N \l_@@_internal_tl +% \end{macrocode} +% \end{variable} +% % \begin{variable}[tested = m3prop004]{\c_empty_prop} -% An empty prop contains exactly one \cs{q_@@}. +% An empty prop is an empty token list. % \begin{macrocode} -\tl_const:Nn \c_empty_prop { \q_@@ } +\cs_new_eq:NN \c_empty_prop \c_empty_tl % \end{macrocode} % \end{variable} % % \subsection{Allocation and initialisation} % -% \begin{macro}[tested = m3prop001]{\prop_new:N,\prop_new:c} -% Internally, property lists are token lists, but an empty prop -% is not an empty tl, so we need to do things by hand. +% \begin{macro}[tested = m3prop001]{\prop_new:N, \prop_new:c} +% Internally, property lists are just token lists. % \begin{macrocode} -\cs_new_protected:Npn \prop_new:N #1 { \cs_new_eq:NN #1 \c_empty_prop } -\cs_new_protected:Npn \prop_new:c #1 { \cs_new_eq:cN {#1} \c_empty_prop } +\cs_new_eq:NN \prop_new:N \tl_new:N +\cs_new_eq:NN \prop_new:c \tl_new:c % \end{macrocode} % \end{macro} % % \begin{macro}[tested = m3prop001]{\prop_clear:N, \prop_clear:c} % \begin{macro}[tested = m3prop001]{\prop_gclear:N, \prop_gclear:c} -% The same idea for clearing +% The same idea for clearing. % \begin{macrocode} -\cs_new_protected:Npn \prop_clear:N #1 { \cs_set_eq:NN #1 \c_empty_prop } -\cs_generate_variant:Nn \prop_clear:N { c } -\cs_new_protected:Npn \prop_gclear:N #1 { \cs_gset_eq:NN #1 \c_empty_prop } -\cs_generate_variant:Nn \prop_gclear:N { c } +\cs_new_eq:NN \prop_clear:N \tl_clear:N +\cs_new_eq:NN \prop_clear:c \tl_clear:c +\cs_new_eq:NN \prop_gclear:N \tl_gclear:N +\cs_new_eq:NN \prop_gclear:c \tl_gclear:c % \end{macrocode} % \end{macro} % \end{macro} @@ -533,12 +547,10 @@ % \begin{macro}[tested = m3prop001]{\prop_gclear_new:N, \prop_gclear_new:c} % Once again a simple copy from the token list functions. % \begin{macrocode} -\cs_new_protected:Npn \prop_clear_new:N #1 - { \prop_if_exist:NTF #1 { \prop_clear:N #1 } { \prop_new:N #1 } } -\cs_generate_variant:Nn \prop_clear_new:N { c } -\cs_new_protected:Npn \prop_gclear_new:N #1 - { \prop_if_exist:NTF #1 { \prop_gclear:N #1 } { \prop_new:N #1 } } -\cs_generate_variant:Nn \prop_gclear_new:N { c } +\cs_new_eq:NN \prop_clear_new:N \tl_clear_new:N +\cs_new_eq:NN \prop_clear_new:c \tl_clear_new:c +\cs_new_eq:NN \prop_gclear_new:N \tl_gclear_new:N +\cs_new_eq:NN \prop_gclear_new:c \tl_gclear_new:c % \end{macrocode} % \end{macro} % \end{macro} @@ -577,67 +589,69 @@ % % \begin{macro}[int]{\@@_split:NnTF} % \begin{macro}[aux]{\@@_split_aux:NnTF} -% \begin{macro}[aux]{\@@_split_aux:nnnn} -% \begin{macro}[aux]{\@@_split_aux:w} +% \begin{macro}[aux, EXP]{\@@_split_aux:w} % This function is used by most of the module, and hence must be fast. -% The aim here is to split a property list at a given key into the part -% before the key--value pair, the value associated with the key and the part -% after the key--value pair. To do this, the key is first detokenized (to -% avoid repeatedly doing this), then a delimited function is constructed to -% match the key. It will match \cs{q_@@} \meta{detokenized key} \cs{q_@@} -% \Arg{value} \meta{extra argument}, effectively separating an -% \meta{extract_1} before the key in the property list and an \meta{extract_2} -% after the key. -% -% If the key is present in the property list, then \meta{extra argument} -% is simply \cs{q_@@}, and \cs{@@_split_aux:nnnn} will gobble this -% and the false branch (|#4|), leaving the correct code on the input -% stream. More precisely, it leaves the user code (true branch), followed -% by three groups, \Arg{extract_1} \Arg{value} \Arg{extract_2}. -% In order for \meta{extract_1}\meta{extract_2} to be a well-formed -% property list, \meta{extract_1} has a leading and trailing \cs{q_@@}, -% retaining exactly the structure of a property list, while \meta{extract_2} -% omits the leading \cs{q_@@}. -% -% If the key is not there, then \meta{extra argument} is |?| -% \cs{use_ii:nn} |{ }|, and \cs{@@_split_aux:nnnn} |?| \cs{use_ii:nn} -% |{ }| removes the three brace groups that just follow. Then -% \cs{use_ii:nn} removes the true branch, leaving the false branch, -% with no trailing material. +% It receives a \meta{property list}, a \meta{key}, a \meta{true code} +% and a \meta{false code}. The aim is to split the \meta{property +% list} at the given \meta{key} into the \meta{extract_1} before the +% key--value pair, the \meta{value} associated with the \meta{key} and +% the \meta{extract_2} after the key--value pair. This is done using +% a delimited function, whose definition is as follows, where the +% \meta{key} is turned into a string. +% \begin{quote} +% \cs{cs_set:Npn} \cs{@@_split_aux:w} |#1| \\ +% \quad \cs{s_@@} \meta{key} \cs{s_@@} |#2| \\ +% \quad |#3| \cs{q_mark} |#4| |#5| \cs{q_stop} \\ +% \quad |{| |#4| \Arg{true code} \Arg{false code} |}| +% \end{quote} +% +% If the \meta{key} is present in the property list, +% \cs{@@_split_aux:w}'s |#1| is the part before the \meta{key}, |#2| +% is the \meta{value}, |#3| is the part after the \meta{key}, |#4| is +% \cs{use_i:nn}, and |#5| is additional tokens that we do not care +% about. The \meta{true code} is left in the input stream, and can +% use the parameters |#1|, |#2|, |#3| for the three parts of the +% property list as desired. +% +% If the \meta{key} is not there, then the \meta{function} is +% \cs{use_ii:nn}, which keeps the \meta{false code}. % \begin{macrocode} \cs_new_protected:Npn \@@_split:NnTF #1#2 { \exp_args:NNo \@@_split_aux:NnTF #1 { \tl_to_str:n {#2} } } -\cs_new_protected:Npn \@@_split_aux:NnTF #1#2 +\cs_new_protected:Npn \@@_split_aux:NnTF #1#2#3#4 { - \cs_set_protected:Npn \@@_split_aux:w - ##1 \q_@@ #2 \q_@@ ##2 ##3 ##4 \q_mark ##5 \q_stop - { \@@_split_aux:nnnn ##3 { {##1 \q_@@ } {##2} {##4} } } - \exp_after:wN \@@_split_aux:w #1 \q_mark - \q_@@ #2 \q_@@ { } { ? \use_ii:nn { } } \q_mark \q_stop + \cs_set:Npn \@@_split_aux:w ##1 + \s_@@ #2 \s_@@ ##2 ##3 \q_mark ##4 ##5 \q_stop + { ##4 {#3} {#4} } + \exp_after:wN \@@_split_aux:w #1 \q_mark \use_i:nn + \s_@@ #2 \s_@@ { } \q_mark \use_ii:nn \q_stop } -\cs_new:Npn \@@_split_aux:nnnn #1#2#3#4 { #3 #2 } -\cs_new_protected:Npn \@@_split_aux:w { } +\cs_new:Npn \@@_split_aux:w { } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} -% \end{macro} % % \begin{macro}[tested = m3prop002] % {\prop_remove:Nn, \prop_remove:NV, \prop_remove:cn, \prop_remove:cV} % \begin{macro}[tested = m3prop002] % {\prop_gremove:Nn, \prop_gremove:NV, \prop_gremove:cn, \prop_gremove:cV} -% \begin{macro}[aux]{\@@_remove:NNnnn} % Deleting from a property starts by splitting the list. % If the key is present in the property list, the returned value is ignored. % If the key is missing, nothing happens. % \begin{macrocode} \cs_new_protected:Npn \prop_remove:Nn #1#2 - { \@@_split:NnTF #1 {#2} { \@@_remove:NNnnn \tl_set:Nn #1 } { } } + { + \@@_split:NnTF #1 {#2} + { \tl_set:Nn #1 { ##1 ##3 } } + { } + } \cs_new_protected:Npn \prop_gremove:Nn #1#2 - { \@@_split:NnTF #1 {#2} { \@@_remove:NNnnn \tl_gset:Nn #1 } { } } -\cs_new_protected:Npn \@@_remove:NNnnn #1#2#3#4#5 - { #1 #2 { #3 #5 } } + { + \@@_split:NnTF #1 {#2} + { \tl_gset:Nn #1 { ##1 ##3 } } + { } + } \cs_generate_variant:Nn \prop_remove:Nn { NV } \cs_generate_variant:Nn \prop_remove:Nn { c , cV } \cs_generate_variant:Nn \prop_gremove:Nn { NV } @@ -645,14 +659,12 @@ % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} % % \begin{macro}[tested = m3prop002] % { % \prop_get:NnN, \prop_get:NVN, \prop_get:NoN, % \prop_get:cnN, \prop_get:cVN, \prop_get:coN % } -% \begin{macro}[aux]{\@@_get:Nnnn} % Getting an item from a list is very easy: after splitting, % if the key is in the property list, just set the token list variable % to the return value, otherwise to \cs{q_no_value}. @@ -660,22 +672,18 @@ \cs_new_protected:Npn \prop_get:NnN #1#2#3 { \@@_split:NnTF #1 {#2} - { \@@_get:Nnnn #3 } + { \tl_set:Nn #3 {##2} } { \tl_set:Nn #3 { \q_no_value } } } -\cs_new_protected:Npn \@@_get:Nnnn #1#2#3#4 - { \tl_set:Nn #1 {#3} } \cs_generate_variant:Nn \prop_get:NnN { NV , No } \cs_generate_variant:Nn \prop_get:NnN { c , cV , co } % \end{macrocode} % \end{macro} -% \end{macro} % % \begin{macro}[tested = m3prop002] % {\prop_pop:NnN, \prop_pop:NoN, \prop_pop:cnN, \prop_pop:coN} % \begin{macro}[tested = m3prop002] % {\prop_gpop:NnN, \prop_gpop:NoN, \prop_gpop:cnN, \prop_gpop:coN} -% \begin{macro}[aux]{\@@_pop:NNNnnn} % Popping a value also starts by doing the split. % If the key is present, save the value in the token list and update the % property list as when deleting. @@ -684,20 +692,21 @@ \cs_new_protected:Npn \prop_pop:NnN #1#2#3 { \@@_split:NnTF #1 {#2} - { \@@_pop:NNNnnn \tl_set:Nn #1 #3 } + { + \tl_set:Nn #3 {##2} + \tl_set:Nn #1 { ##1 ##3 } + } { \tl_set:Nn #3 { \q_no_value } } } \cs_new_protected:Npn \prop_gpop:NnN #1#2#3 { \@@_split:NnTF #1 {#2} - { \@@_pop:NNNnnn \tl_gset:Nn #1 #3 } + { + \tl_set:Nn #3 {##2} + \tl_gset:Nn #1 { ##1 ##3 } + } { \tl_set:Nn #3 { \q_no_value } } } -\cs_new_protected:Npn \@@_pop:NNNnnn #1#2#3#4#5#6 - { - \tl_set:Nn #3 {#5} - #1 #2 { #4 #6 } - } \cs_generate_variant:Nn \prop_pop:NnN { No } \cs_generate_variant:Nn \prop_pop:NnN { c , co } \cs_generate_variant:Nn \prop_gpop:NnN { No } @@ -705,11 +714,9 @@ % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} % % \begin{macro}[TF, tested = m3prop004] % {\prop_pop:NnN, \prop_pop:cnN, \prop_gpop:NnN, \prop_gpop:cnN} -% \begin{macro}[aux]{\@@_pop_true:NNNnnn} % Popping an item from a property list, keeping track of whether % the key was present or not, is implemented as a conditional. % If the key was missing, neither the property list, nor the token @@ -719,21 +726,23 @@ \prg_new_protected_conditional:Npnn \prop_pop:NnN #1#2#3 { T , F , TF } { \@@_split:NnTF #1 {#2} - { \@@_pop_true:NNNnnn \tl_set:Nn #1 #3 } + { + \tl_set:Nn #3 {##2} + \tl_set:Nn #1 { ##1 ##3 } + \prg_return_true: + } { \prg_return_false: } } \prg_new_protected_conditional:Npnn \prop_gpop:NnN #1#2#3 { T , F , TF } { \@@_split:NnTF #1 {#2} - { \@@_pop_true:NNNnnn \tl_gset:Nn #1 #3 } + { + \tl_set:Nn #3 {##2} + \tl_gset:Nn #1 { ##1 ##3 } + \prg_return_true: + } { \prg_return_false: } } -\cs_new_protected:Npn \@@_pop_true:NNNnnn #1#2#3#4#5#6 - { - \tl_set:Nn #3 {#5} - #1 #2 { #4 #6 } - \prg_return_true: - } \cs_generate_variant:Nn \prop_pop:NnNT { c } \cs_generate_variant:Nn \prop_pop:NnNF { c } \cs_generate_variant:Nn \prop_pop:NnNTF { c } @@ -742,7 +751,6 @@ \cs_generate_variant:Nn \prop_gpop:NnNTF { c } % \end{macrocode} % \end{macro} -% \end{macro} % % \begin{macro}[tested = m3prop002] % { @@ -758,32 +766,31 @@ % \prop_gput:cnn, \prop_gput:cnV, \prop_gput:cno, \prop_gput:cnx, % \prop_gput:cVn, \prop_gput:cVV, \prop_gput:con, \prop_gput:coo % } -% \begin{macro}[aux]{\@@_put:NNNnn, \@@_put:NNnnnnn} -% Putting a key--value pair in a property list starts by splitting to -% remove any existing value. If the \meta{key} was absent, append the -% new key--value pair. Otherwise, the property list is reconstructed -% from the two remaining parts |#5| and |#7|, and the updated entry. -% The updated entry is placed at the same spot as the original -% \meta{key} in the property list, preserving the order of entries. +% \begin{macro}[aux]{\@@_put:NNNnn} +% Since the branches of \cs{@@_split:NnTF} are used as the replacement +% text of an internal macro, and since the \meta{key} and new +% \meta{value} may contain arbitrary tokens, it is not safe to include +% them in the argument of \cs{@@_split:NnTF}. We thus start by +% storing in \cs{l_@@_internal_tl} tokens which (after +% \texttt{x}-expansion) encode the key--value pair. This variable can +% safely be used in \cs{@@_split:NnTF}. If the \meta{key} was absent, +% append the new key--value to the list. Otherwise concatenate the +% extracts |##1| and |##3| with the new key--value pair +% \cs{l_@@_internal_tl}. The updated entry is placed at the same spot +% as the original \meta{key} in the property list, preserving the +% order of entries. % \begin{macrocode} -\cs_new_protected:Npn \prop_put:Nnn +\cs_new_protected_nopar:Npn \prop_put:Nnn { \@@_put:NNNnn \tl_set:Nx \tl_put_right:Nx } -\cs_new_protected:Npn \prop_gput:Nnn +\cs_new_protected_nopar:Npn \prop_gput:Nnn { \@@_put:NNNnn \tl_gset:Nx \tl_gput_right:Nx } \cs_new_protected:Npn \@@_put:NNNnn #1#2#3#4#5 { + \tl_set:Nn \l_@@_internal_tl + { \s_@@ \tl_to_str:n {#4} \s_@@ { \exp_not:n {#5} } } \@@_split:NnTF #3 {#4} - { \@@_put:NNnnnnn #1 #3 {#4} {#5} } - { #2 #3 { \tl_to_str:n {#4} \exp_not:n { \q_@@ {#5} \q_@@ } } } - } -\cs_new_protected:Npn \@@_put:NNnnnnn #1#2#3#4#5#6#7 - { - #1 #2 - { - \exp_not:n {#5} - \tl_to_str:n {#3} \exp_not:n { \q_@@ {#4} \q_@@ } - \exp_not:n {#7} - } + { #1 #3 { \exp_not:n {##1} \l_@@_internal_tl \exp_not:n {##3} } } + { #2 #3 { \l_@@_internal_tl } } } \cs_generate_variant:Nn \prop_put:Nnn { NnV , Nno , Nnx , NV , NVV , No , Noo } @@ -814,12 +821,11 @@ { \@@_put_if_new:NNnn \tl_gput_right:Nx } \cs_new_protected:Npn \@@_put_if_new:NNnn #1#2#3#4 { + \tl_set:Nn \l_@@_internal_tl + { \s_@@ \tl_to_str:n {#3} \s_@@ \exp_not:n { {#4} } } \@@_split:NnTF #2 {#3} - { \use_none:nnn } - { - #1 #2 - { \tl_to_str:n {#3} \exp_not:n { \q_@@ {#4} \q_@@ } } - } + { } + { #1 #2 { \l_@@_internal_tl } } } \cs_generate_variant:Nn \prop_put_if_new:Nnn { c } \cs_generate_variant:Nn \prop_gput_if_new:Nnn { c } @@ -833,32 +839,18 @@ % \begin{macro}[pTF, tested = m3prop004]{\prop_if_exist:N, \prop_if_exist:c} % Copies of the \texttt{cs} functions defined in \pkg{l3basics}. % \begin{macrocode} -\cs_new_eq:NN \prop_if_exist:NTF \cs_if_exist:NTF -\cs_new_eq:NN \prop_if_exist:NT \cs_if_exist:NT -\cs_new_eq:NN \prop_if_exist:NF \cs_if_exist:NF -\cs_new_eq:NN \prop_if_exist_p:N \cs_if_exist_p:N -\cs_new_eq:NN \prop_if_exist:cTF \cs_if_exist:cTF -\cs_new_eq:NN \prop_if_exist:cT \cs_if_exist:cT -\cs_new_eq:NN \prop_if_exist:cF \cs_if_exist:cF -\cs_new_eq:NN \prop_if_exist_p:c \cs_if_exist_p:c +\prg_new_eq_conditional:NNn \prop_if_exist:N \cs_if_exist:N { TF , T , F , p } +\prg_new_eq_conditional:NNn \prop_if_exist:c \cs_if_exist:c { TF , T , F , p } % \end{macrocode} % \end{macro} % % \begin{macro}[pTF, tested = m3prop003]{\prop_if_empty:N, \prop_if_empty:c} -% The test here uses \cs{c_empty_prop} as it is not really empty! +% Same test as for token lists. % \begin{macrocode} -\prg_new_conditional:Npnn \prop_if_empty:N #1 { p, T , F , TF } - { - \if_meaning:w #1 \c_empty_prop - \prg_return_true: - \else: - \prg_return_false: - \fi: - } -\cs_generate_variant:Nn \prop_if_empty_p:N {c} -\cs_generate_variant:Nn \prop_if_empty:NTF {c} -\cs_generate_variant:Nn \prop_if_empty:NT {c} -\cs_generate_variant:Nn \prop_if_empty:NF {c} +\prg_new_eq_conditional:NNn \prop_if_empty:N \tl_if_empty:N + { p , T , F , TF } +\prg_new_eq_conditional:NNn \prop_if_empty:c \tl_if_empty:c + { p , T , F , TF } % \end{macrocode} % \end{macro} % @@ -885,12 +877,12 @@ % but \cs{@@_split:NnTF} is non-expandable. % % Instead, the key is compared to each key in turn using \cs{str_if_eq_x:nn}, -% which is expandable. To terminate the mapping, we add the key that -% is search for at the end of the property list. This second +% which is expandable. To terminate the mapping, we append to the property +% list the key that is searched for. This second % \cs{tl_to_str:n} is not expanded at the start, but only when included % in the \cs{str_if_eq_x:nn}. It cannot make the breaking mechanism choke, % because the arbitrary token list material is enclosed in braces. -% When ending, we test the next token: it is either \cs{q_@@} +% When ending, we test the next token: it is either \cs{s_@@} % or \cs{q_recursion_tail} in the case of a missing key. % Here, \cs{prop_map_function:NN} is not sufficient for the mapping, % since it can only map a single token, and cannot carry the key that @@ -900,11 +892,11 @@ { \exp_last_unbraced:Noo \@@_if_in:nwn { \tl_to_str:n {#2} } #1 - \tl_to_str:n {#2} \q_@@ { } - \q_recursion_tail % could be any cs != \q_@@ + \s_@@ \tl_to_str:n {#2} \s_@@ { } + \q_recursion_tail \__prg_break_point: } -\cs_new:Npn \@@_if_in:nwn #1 \q_@@ #2 \q_@@ #3 +\cs_new:Npn \@@_if_in:nwn #1 \s_@@ #2 \s_@@ #3 { \str_if_eq_x:nnTF {#1} {#2} { \@@_if_in:N } @@ -912,7 +904,7 @@ } \cs_new:Npn \@@_if_in:N #1 { - \if_meaning:w \q_@@ #1 + \if_meaning:w \s_@@ #1 \prg_return_true: \else: \prg_return_false: @@ -938,7 +930,6 @@ % \prop_get:NnN, \prop_get:NVN, \prop_get:NoN, % \prop_get:cnN, \prop_get:cVN, \prop_get:coN % } -% \begin{macro}[aux]{\@@_get_true:Nnnn} % Getting the value corresponding to a key, keeping track of whether % the key was present or not, is implemented as a conditional (with % side effects). If the key was absent, the token list is not altered. @@ -946,14 +937,12 @@ \prg_new_protected_conditional:Npnn \prop_get:NnN #1#2#3 { T , F , TF } { \@@_split:NnTF #1 {#2} - { \@@_get_true:Nnnn #3 } + { + \tl_set:Nn #3 {##2} + \prg_return_true: + } { \prg_return_false: } } -\cs_new_protected:Npn \@@_get_true:Nnnn #1#2#3#4 - { - \tl_set:Nn #1 {#3} - \prg_return_true: - } \cs_generate_variant:Nn \prop_get:NnNT { NV , No } \cs_generate_variant:Nn \prop_get:NnNF { NV , No } \cs_generate_variant:Nn \prop_get:NnNTF { NV , No } @@ -962,7 +951,6 @@ \cs_generate_variant:Nn \prop_get:NnNTF { c , cV , co } % \end{macrocode} % \end{macro} -% \end{macro} % % \subsection{Mapping to property lists} % @@ -972,19 +960,24 @@ % \prop_map_function:cN, \prop_map_function:cc % } % \begin{macro}[aux]{\@@_map_function:Nwn} -% The fastest way to do a recursion here would be to use an +% The fastest way to do a recursion here is to use an % \cs{if_meaning:w} test: the keys are strings, and thus % cannot match the marker \cs{q_recursion_tail}. +% A special case to note is when the key |#2| is empty: +% then \cs{q_recursion_tail} is compared to \cs{exp_after:wN}, +% also different. % \begin{macrocode} \cs_new:Npn \prop_map_function:NN #1#2 { \exp_last_unbraced:NNo \@@_map_function:Nwn #2 - #1 \q_recursion_tail \q_@@ { } + #1 \s_@@ \q_recursion_tail \s_@@ { } \__prg_break_point:Nn \prop_map_break: { } } -\cs_new:Npn \@@_map_function:Nwn #1 \q_@@ #2 \q_@@ #3 +\cs_new:Npn \@@_map_function:Nwn #1 \s_@@ #2 \s_@@ #3 { - \__quark_if_recursion_tail_break:nN {#2} \prop_map_break: + \if_meaning:w \q_recursion_tail #2 + \exp_after:wN \prop_map_break: + \fi: #1 {#2} {#3} \@@_map_function:Nwn #1 } @@ -1004,7 +997,7 @@ \exp_last_unbraced:Nco \@@_map_function:Nwn { __prg_map_ \int_use:N \g__prg_map_int :w } #1 - \q_recursion_tail \q_@@ { } + \s_@@ \q_recursion_tail \s_@@ { } \__prg_break_point:Nn \prop_map_break: { \int_gdecr:N \g__prg_map_int } } \cs_generate_variant:Nn \prop_map_inline:Nn { c } @@ -1119,6 +1112,7 @@ % \begin{macro}{\prop_del:Nn, \prop_del:NV, \prop_del:cn, \prop_del:cV} % \begin{macro}{\prop_gdel:Nn, \prop_gdel:NV, \prop_gdel:cn, \prop_gdel:cV} % \begin{macrocode} +%<*deprecated> \cs_new_eq:NN \prop_del:Nn \prop_remove:Nn \cs_new_eq:NN \prop_del:NV \prop_remove:NV \cs_new_eq:NN \prop_del:cn \prop_remove:cn @@ -1127,6 +1121,7 @@ \cs_new_eq:NN \prop_gdel:NV \prop_gremove:NV \cs_new_eq:NN \prop_gdel:cn \prop_gremove:cn \cs_new_eq:NN \prop_gdel:cV \prop_gremove:cV +%</deprecated> % \end{macrocode} % \end{macro} % \end{macro} |