summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3prop.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3prop.dtx1206
1 files changed, 1206 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx
new file mode 100644
index 00000000000..744cea629fc
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx
@@ -0,0 +1,1206 @@
+% \iffalse meta-comment
+%
+%% File: l3prop.dtx Copyright (C) 1990-2011 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
+%% license or (at your option) any later version. The latest version
+%% of this license is in the file
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This file is part of the "expl3 bundle" (The Work in LPPL)
+%% and all files in that bundle must be distributed together.
+%%
+%% The released version of this bundle is available from CTAN.
+%%
+%% -----------------------------------------------------------------------
+%%
+%% The development version of the bundle can be found at
+%%
+%% http://www.latex-project.org/svnroot/experimental/trunk/
+%%
+%% for those people who are interested.
+%%
+%%%%%%%%%%%
+%% NOTE: %%
+%%%%%%%%%%%
+%%
+%% Snapshots taken from the repository represent work in progress and may
+%% not work or may contain conflicting material! We therefore ask
+%% people _not_ to put them into distributions, archives, etc. without
+%% prior consultation with the LaTeX3 Project.
+%%
+%% -----------------------------------------------------------------------
+%
+%<*driver|package>
+\RequirePackage{l3names}
+\GetIdInfo$Id: l3prop.dtx 2478 2011-06-19 21:34:23Z joseph $
+ {L3 Experimental property lists}
+%</driver|package>
+%<*driver>
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+% The \pkg{l3prop} package\\ Property lists^^A
+% \thanks{This file describes v\ExplFileVersion,
+% last revised \ExplFileDate.}^^A
+% }
+%
+% \author{^^A
+% The \LaTeX3 Project\thanks
+% {^^A
+% E-mail:
+% \href{mailto:latex-team@latex-project.org}
+% {latex-team@latex-project.org}^^A
+% }^^A
+% }
+%
+% \date{Released \ExplFileDate}
+%
+% \maketitle
+%
+% \begin{documentation}
+%
+% \LaTeX3 implements a \enquote{property list} data type, which contain
+% an unordered list of entries each of which consists of a \meta{key} and
+% an associated \meta{value}. The \meta{key} and \meta{value} may both be
+% any \meta{balanced text}. It is possible to map functions to property lists
+% such that the function is applied to every key--value pair within
+% the list.
+%
+% Each entry in a property list must have a unique \meta{key}: if an entry is
+% added to a property list which already contains the \meta{key} then the new
+% entry will overwrite the existing one. The \meta{keys} are compared on a
+% string basis, using the same method as \cs{str_if_eq:nn}.
+%
+% \section{Creating and initialising property lists}
+%
+% \begin{function}{\prop_new:N, \prop_new:c}
+% \begin{syntax}
+% \cs{prop_new:N} \meta{property list}
+% \end{syntax}
+% Creates a new \meta{property list} or raises an error if the name is
+% already taken. The declaration is global. The \meta{property lists} will
+% initially contain no entries.
+% \end{function}
+%
+% \begin{function}{\prop_clear:N, \prop_clear:c}
+% \begin{syntax}
+% \cs{prop_clear:N} \meta{property list}
+% \end{syntax}
+% Clears all entries from the \meta{property list} within the scope of
+% the current \TeX{} group.
+% \end{function}
+%
+% \begin{function}{\prop_gclear:N, \prop_gclear:c}
+% \begin{syntax}
+% \cs{prop_gclear:N} \meta{property list}
+% \end{syntax}
+% Clears all entries from the \meta{property list} globally.
+% \end{function}
+%
+% \begin{function}{\prop_clear_new:N, \prop_clear_new:c}
+% \begin{syntax}
+% \cs{prop_clear_new:N} \meta{property list}
+% \end{syntax}
+% If the \meta{property list} already exists, clears it within the scope
+% of the current \TeX{} group. If the \meta{property list} is not defined,
+% it will be created (using \cs{prop_new:N}). Thus the property list is
+% guaranteed to be available and clear within the current \TeX{}
+% group. The \meta{property list} will exist globally, but the content
+% outside of the current \TeX{} group is not specified.
+% \end{function}
+%
+% \begin{function}{\prop_gclear_new:N, \prop_gclear_new:c}
+% \begin{syntax}
+% \cs{prop_gclear_new:N} \meta{property list}
+% \end{syntax}
+% If the \meta{property list} already exists, clears it globally. If the
+% \meta{property list} is not defined, it will be created (using
+% \cs{prop_new:N}). Thus the property list is guaranteed to be available
+% and globally clear.
+% \end{function}
+%
+% \begin{function}
+% {\prop_set_eq:NN, \prop_set_eq:cN, \prop_set_eq:Nc, \prop_set_eq:cc}
+% \begin{syntax}
+% \cs{prop_set_eq:NN} \meta{property list1} \meta{property list2}
+% \end{syntax}
+% Sets the content of \meta{property list1} equal to that of
+% \meta{property list2}. This assignment is restricted to the current
+% \TeX{} group level.
+% \end{function}
+%
+% \begin{function}
+% {\prop_gset_eq:NN, \prop_gset_eq:cN, \prop_gset_eq:Nc, \prop_gset_eq:cc}
+% \begin{syntax}
+% \cs{prop_gset_eq:NN} \meta{property list1} \meta{property list2}
+% \end{syntax}
+% Sets the content of \meta{property list1} equal to that of
+% \meta{property list2}. This assignment is global and so is not
+% limited by the current \TeX{} group level.
+% \end{function}
+%
+% \section{Adding entries to property lists}
+%
+% \begin{function}
+% {
+% \prop_put:Nnn, \prop_put:NnV, \prop_put:Nno, \prop_put:Nnx,
+% \prop_put:NVn, \prop_put:NVV, \prop_put:Non, \prop_put:Noo,
+% \prop_put:cnn, \prop_put:cnV, \prop_put:cno, \prop_put:cnx,
+% \prop_put:cVn, \prop_put:cVV, \prop_put:con, \prop_put:coo
+% }
+% \begin{syntax}
+% \cs{prop_put:Nnn} \meta{property list} \Arg{key} \Arg{value}
+% \end{syntax}
+% Adds an entry to the \meta{property list} which may be accessed
+% using the \meta{key} and which has \meta{value}. Both the \meta{key}
+% and \meta{value} may contain any \meta{balanced text}. The \meta{key}
+% is stored after processing with \cs{tl_to_str:n}, meaning that
+% category codes are ignored. If the \meta{key} is already present
+% in the \meta{property list}, the existing entry is overwritten
+% by the new \meta{value}. The assignment is restricted to the current
+% \TeX{} group.
+% \end{function}
+%
+% \begin{function}
+% {
+% \prop_gput:Nnn, \prop_gput:NnV, \prop_gput:Nno, \prop_gput:Nnx,
+% \prop_gput:NVn, \prop_gput:NVV, \prop_gput:Non, \prop_gput:Noo,
+% \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{syntax}
+% \cs{prop_gput:Nnn} \meta{property list} \Arg{key} \Arg{value}
+% \end{syntax}
+% Adds an entry to the \meta{property list} which may be accessed
+% using the \meta{key} and which has \meta{value}. Both the \meta{key}
+% and \meta{value} may contain any \meta{balanced text}. The \meta{key}
+% is stored after processing with \cs{tl_to_str:n}, meaning that
+% category codes are ignored. If the \meta{key} is already present
+% in the \meta{property list}, the existing entry is overwritten
+% by the new \meta{value}. The assignment is global.
+% \end{function}
+%
+% \begin{function}{\prop_put_if_new:Nnn, \prop_put_if_new:cnn}
+% \begin{syntax}
+% \cs{prop_put_if_new:Nnn} \meta{property list} \Arg{key} \Arg{value}
+% \end{syntax}
+% If the \meta{key} is present in the \meta{property list} then
+% no action is taken. If the \meta{key} is not present in the
+% \meta{property list} then a new entry is added. Both the \meta{key}
+% and \meta{value} may contain any \meta{balanced text}. The \meta{key}
+% is stored after processing with \cs{tl_to_str:n}, meaning that
+% category codes are ignored. The assignment is restricted to the current
+% \TeX{} group.
+% \end{function}
+%
+% \begin{function}{\prop_gput_if_new:Nnn, \prop_gput_if_new:cnn}
+% \begin{syntax}
+% \cs{prop_gput_if_new:Nnn} \meta{property list} \Arg{key} \Arg{value}
+% \end{syntax}
+% If the \meta{key} is present in the \meta{property list} then
+% no action is taken. If the \meta{key} is not present in the
+% \meta{property list} then a new entry is added. Both the \meta{key}
+% and \meta{value} may contain any \meta{balanced text}. The \meta{key}
+% is stored after processing with \cs{tl_to_str:n}, meaning that
+% category codes are ignored. The assignment is global.
+% \end{function}
+%
+% \section{Recovering values from property lists}
+%
+% \begin{function}
+% {
+% \prop_get:NnN, \prop_get:NVN, \prop_get:NoN,
+% \prop_get:cnN, \prop_get:cVN, \prop_get:coN,
+% }
+% \begin{syntax}
+% \cs{prop_get:NnN} \meta{property list} \Arg{key} \meta{tl var}
+% \end{syntax}
+% Recovers the \meta{value} stored with \meta{key} from the
+% \meta{property list}, and places this in the \meta{token list
+% variable}. If the \meta{key} is not found in the
+% \meta{property list} then the \meta{token list variable} will
+% contain the special marker \cs{q_no_value}. The \meta{token list
+% variable} is set within the current \TeX{} group.
+% \end{function}
+%
+% \begin{function}{\prop_pop:NnN, \prop_pop:NoN, \prop_pop:cnN, \prop_pop:coN}
+% \begin{syntax}
+% \cs{prop_pop:NnN} \meta{property list} \Arg{key} \meta{tl var}
+% \end{syntax}
+% Recovers the \meta{value} stored with \meta{key} from the
+% \meta{property list}, and places this in the \meta{token list
+% variable}. If the \meta{key} is not found in the
+% \meta{property list} then the \meta{token list variable} will
+% contain the special marker \cs{q_no_value}. The \meta{key} and
+% \meta{value} are then deleted from the property list. Both
+% assignments are local.
+% \end{function}
+%
+% \begin{function}
+% {\prop_gpop:NnN, \prop_gpop:NoN, \prop_gpop:cnN, \prop_gpop:coN}
+% \begin{syntax}
+% \cs{prop_gpop:NnN} \meta{property list} \Arg{key} \meta{tl var}
+% \end{syntax}
+% Recovers the \meta{value} stored with \meta{key} from the
+% \meta{property list}, and places this in the \meta{token list
+% variable}. If the \meta{key} is not found in the
+% \meta{property list} then the \meta{token list variable} will
+% contain the special marker \cs{q_no_value}. The \meta{key} and
+% \meta{value} are then deleted from the property list.
+% The \meta{property list} is modified globally, while the assignment of
+% the \meta{token list variable} is local.
+% \end{function}
+%
+% \section{Modifying property lists}
+%
+% \begin{function}{\prop_del:Nn, \prop_del:NV, \prop_del:cn, \prop_del:cV}
+% \begin{syntax}
+% \cs{prop_del:Nn} \meta{property list} \Arg{key}
+% \end{syntax}
+% Deletes the entry listed under \meta{key} from the
+% \meta{property list} which may be accessed. If the \meta{key} is
+% not found in the \meta{property list} no change occurs,
+% \emph{i.e}~there is no need to test for the existence of a key before
+% deleting it. The deletion is restricted to the current \TeX{} group.
+% \end{function}
+%
+% \begin{function}{\prop_gdel:Nn, \prop_gdel:NV, \prop_gdel:cn, \prop_gdel:cV}
+% \begin{syntax}
+% \cs{prop_gdel:Nn} \meta{property list} \Arg{key}
+% \end{syntax}
+% Deletes the entry listed under \meta{key} from the
+% \meta{property list} which may be accessed. If the \meta{key} is
+% not found in the \meta{property list} no change occurs,
+% \emph{i.e}~there is no need to test for the existence of a key before
+% deleting it. The deletion is not restricted to the current \TeX{}
+% group: it is global.
+% \end{function}
+%
+% \section{Property list conditionals}
+%
+% \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}
+% \end{syntax}
+% Tests if the \meta{property list} is empty (containing no entries). The
+% branching versions then leave either \meta{true code} or
+% \meta{false code} in the input stream, as appropriate to the truth of
+% the test and the variant of the function chosen. The logical truth of
+% the test is left in the input stream by the predicate version.
+% \end{function}
+%
+% \begin{function}[EXP,pTF]{
+% \prop_if_in:Nn, \prop_if_in:NV, \prop_if_in:No,
+% \prop_if_in:cn, \prop_if_in:cV, \prop_if_in:co
+% }
+% \begin{syntax}
+% \cs{prop_if_in:NnTF} \meta{property list} \Arg{key}
+% ~~\Arg{true code} \Arg{false code}
+% \end{syntax}
+% Tests if the \meta{key} is present in the \meta{property list},
+% making the comparison using the method described by \cs{str_if_eq:nnTF}.
+% Either the \meta{true code} or \meta{false code} in the input stream, as
+% appropriate to the truth of the test and the variant of the function
+% chosen.
+% \begin{texnote}
+% This function iterates through every key--value pair in the
+% \meta{property list} and is therefore slower than using the
+% non-expandable \cs{prop_get:NnNTF}.
+% \end{texnote}
+% \end{function}
+%
+% \section{Mapping to property lists}
+%
+% \begin{function}[EXP]{\prop_map_function:NN, \prop_map_function:cN}
+% \begin{syntax}
+% \cs{prop_map_function:NN} \meta{property list} \meta{function}
+% \end{syntax}
+% Applies \meta{function} to every \meta{entry} stored in the
+% \meta{property list}. The \meta{function} will receive two argument for
+% each iteration.: the \meta{key} and associated \meta{value}.
+% The order in which \meta{entries} are returned is not defined and
+% should not be relied upon.
+% \end{function}
+%
+% \begin{function}{\prop_map_inline:Nn, \prop_map_inline:cn}
+% \begin{syntax}
+% \cs{prop_map_inline:Nn} \meta{property list} \Arg{inline function}
+% \end{syntax}
+% Applies \meta{inline function} to every \meta{entry} stored
+% within the \meta{property list}. The \meta{inline function} should
+% consist of code which will receive the \meta{key} as |#1| and the
+% \meta{value} as |#2|.
+% The order in which \meta{entries} are returned is not defined and
+% should not be relied upon.
+% \end{function}
+%
+% \begin{function}[EXP]{\prop_map_break:}
+% \begin{syntax}
+% \cs{prop_map_break:}
+% \end{syntax}
+% Used to terminate a \cs{prop_map_\ldots} function before all
+% entries in the \meta{property list} have been processed. This will
+% normally take place within a conditional statement, for example
+% \begin{verbatim}
+% \prop_map_inline:Nn \l_my_prop
+% {
+% \str_if_eq:nnTF { #1 } { bingo }
+% { \prop_map_break: }
+% {
+% % Do something useful
+% }
+% }
+% \end{verbatim}
+% Use outside of a \cs{prop_map_\ldots} scenario will lead low
+% level \TeX{} errors.
+% \end{function}
+%
+% \begin{function}[EXP]{\prop_map_break:n}
+% \begin{syntax}
+% \cs{prop_map_break:n} \Arg{tokens}
+% \end{syntax}
+% Used to terminate a \cs{prop_map_\ldots} function before all
+% entries in the \meta{property list} have been processed, inserting
+% the \meta{tokens} after the mapping has ended. This will
+% normally take place within a conditional statement, for example
+% \begin{verbatim}
+% \prop_map_inline:Nn \l_my_prop
+% {
+% \str_if_eq:nnTF { #1 } { bingo }
+% { \prop_map_break:n { <tokens> } }
+% {
+% % Do something useful
+% }
+% }
+% \end{verbatim}
+% Use outside of a \cs{prop_map_\ldots} scenario will lead low
+% level \TeX{} errors.
+% \end{function}
+%
+% \section{Viewing property lists}
+%
+% \begin{function}{\prop_show:N, \prop_show:c}
+% \begin{syntax}
+% \cs{prop_show:N} \meta{property list}
+% \end{syntax}
+% Displays the entries in the \meta{property list} in the terminal.
+% \end{function}
+%
+% \section{Experimental property list functions}
+%
+% This section contains functions which may or may not be retained, depending
+% on how useful they are found to be.
+%
+% \begin{function}[TF]{\prop_get:NnN}
+% \begin{syntax}
+% \cs{prop_get:NnNTF} \meta{property list} \Arg{key}
+% ~~\meta{token list variable} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% If the \meta{key} is not present in the \meta{property list}, leaves
+% the \meta{false code} in the input stream and leaves the
+% \meta{token list variable} unchanged. If the \meta{key} is present in
+% the \meta{property list}, stores the corresponding \meta{value}
+% in the \meta{token list variable} without removing it from the
+% \meta{property list}. The \meta{true code} is then left in the input
+% stream. The \meta{token list variable} is assigned locally.
+% \end{function}
+%
+% \begin{function}[TF]{\prop_pop:NnN}
+% \begin{syntax}
+% \cs{prop_pop:NnNTF} \meta{property list} \Arg{key}
+% ~~\meta{token list variable} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% If the \meta{key} is not present in the \meta{property list}, leaves
+% the \meta{false code} in the input stream and leaves the
+% \meta{token list variable} unchanged. If the \meta{key} is present in
+% the \meta{property list}, pops the corresponding \meta{value}
+% in the \meta{token list variable}, \emph{i.e.}~removes the item from
+% the \meta{property list}. The \meta{true code} is then left in the input
+% stream. Both the \meta{property list} and the \meta{token list variable}
+% are assigned locally.
+% \end{function}
+%
+% \begin{function}[TF]{\prop_gpop:NnN}
+% \begin{syntax}
+% \cs{prop_gpop:NnNTF} \meta{property list} \Arg{key}
+% ~~\meta{token list variable} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% If the \meta{key} is not present in the \meta{property list}, leaves
+% the \meta{false code} in the input stream and leaves the
+% \meta{token list variable} unchanged. If the \meta{key} is present in
+% the \meta{property list}, pops the corresponding \meta{value}
+% in the \meta{token list variable}, \emph{i.e.}~removes the item from
+% the \meta{property list}. The \meta{true code} is then left in the input
+% stream. The \meta{property list} is modified globally, while the
+% \meta{token list variable} is assigned locally.
+% \end{function}
+%
+% \begin{function}[EXP]{\prop_map_tokens:Nn}
+% \begin{syntax}
+% \cs{prop_map_tokens:Nn} \meta{property list} \Arg{code}
+% \end{syntax}
+% Analogue of \cs{prop_map_function:NN} which maps several tokens instead
+% of a single function. Useful in particular when mapping through a
+% property list while keeping track of a given key.
+% \end{function}
+%
+% \begin{function}[EXP]{\prop_get:Nn}
+% \begin{syntax}
+% \cs{prop_get:Nn} \meta{property list} \Arg{key}
+% \end{syntax}
+% Expands to the \meta{value} corresponding to the \meta{key} in
+% the \meta{property list}. If the \meta{key} is missing, this has
+% an empty expansion.
+% \begin{texnote}
+% This function is slower than the non-expandable analogue
+% \cs{prop_get:NnN}.
+% \end{texnote}
+% \end{function}
+%
+% \section{Internal property list functions}
+%
+% \begin{function}{\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.
+% \end{function}
+%
+% \begin{function}{\c_empty_prop}
+% A permanently-empty property list used for internal comparisons.
+% \end{function}
+%
+% \begin{function}{\prop_split:Nnn}
+% \begin{syntax}
+% \cs{prop_spilt:Nnn} \meta{property list} \Arg{key} \Arg{code}
+% \end{syntax}
+% Splits the \meta{property list} at the \meta{key}, giving three
+% groups: 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
+% property list.
+% If the \meta{key} is not present in the \meta{property list} then
+% the second group will contain the marker \cs{q_no_value} and the third
+% is empty.
+% Once the split has occurred, the \meta{code} is inserted followed by the
+% three groups: thus the \meta{code} should properly absorb three
+% arguments.
+% The \meta{key} comparison takes place as described for \cs{str_if_eq:nn}.
+% \end{function}
+%
+% \begin{function}{\prop_split:NnTF}
+% \begin{syntax}
+% \cs{prop_spilt: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
+% \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
+% 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.
+% 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.
+% The \meta{key} comparison takes place as described for \cs{str_if_eq:nn}.
+% \end{function}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3prop} implementation}
+%
+% \TestFiles{m3prop001}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*package>
+\ProvidesExplPackage
+ {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
+\package_check_loaded_expl:
+%</package>
+% \end{macrocode}
+%
+% A property list is a macro whose top-level expansion is for the form
+% \enquote{\cs{q_prop} \meta{key$_0$} \cs{q_prop} \Arg{value$_0$} \cs{q_prop}
+% \ldots \cs{q_prop} \meta{key$_{n-1}$} \cs{q_prop} \Arg{value$_{n-1}$}
+% \cs{q_prop}}.
+% The trailing \cs{q_prop} is always present for performance reasons: this
+% means that empty property lists are not actually empty.
+%
+% \begin{macro}[int]{\q_prop}
+% A private quark is used as a marker between entries.
+% \begin{macrocode}
+\quark_new:N \q_prop
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\c_empty_prop}
+% An empty prop contains exactly one \cs{q_prop}.
+% \begin{macrocode}
+\tl_const:Nn \c_empty_prop { \q_prop }
+% \end{macrocode}
+% \end{variable}
+%
+% \subsection{Allocation and initialisation}
+%
+% \begin{macro}{\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{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 }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\prop_clear:N, \prop_clear:c}
+% \begin{macro}{\prop_gclear:N, \prop_gclear:c}
+% The same idea for clearing
+% \begin{macrocode}
+\cs_new_protected:Npn \prop_clear:N #1 { \cs_set_eq:NN #1 \c_empty_prop }
+\cs_new_protected:Npn \prop_clear:c #1 { \cs_set_eq:cN {#1} \c_empty_prop }
+\cs_new_protected:Npn \prop_gclear:N #1 { \cs_gset_eq:NN #1 \c_empty_prop }
+\cs_new_protected:Npn \prop_gclear:c #1 { \cs_gset_eq:cN {#1} \c_empty_prop }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\prop_clear_new:N, \prop_clear_new:c}
+% \begin{macro}{\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
+ { \cs_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
+ { \cs_if_exist:NTF #1 { \prop_gclear:N #1 } { \prop_new:N #1 } }
+\cs_new_eq:NN \prop_gclear_new:c \prop_gclear:c
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+% {\prop_set_eq:NN, \prop_set_eq:cN, \prop_set_eq:Nc, \prop_set_eq:cc}
+% \begin{macro}
+% {\prop_gset_eq:NN, \prop_gset_eq:cN, \prop_gset_eq:Nc, \prop_gset_eq:cc}
+% Once again, these are simply copies from the token list functions.
+% \begin{macrocode}
+\cs_new_eq:NN \prop_set_eq:NN \tl_set_eq:NN
+\cs_new_eq:NN \prop_set_eq:Nc \tl_set_eq:Nc
+\cs_new_eq:NN \prop_set_eq:cN \tl_set_eq:cN
+\cs_new_eq:NN \prop_set_eq:cc \tl_set_eq:cc
+\cs_new_eq:NN \prop_gset_eq:NN \tl_gset_eq:NN
+\cs_new_eq:NN \prop_gset_eq:Nc \tl_gset_eq:Nc
+\cs_new_eq:NN \prop_gset_eq:cN \tl_gset_eq:cN
+\cs_new_eq:NN \prop_gset_eq:cc \tl_gset_eq:cc
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Accessing data in property lists}
+%
+% \begin{macro}[int]{\prop_split:NnTF}
+% \begin{macro}[aux]{\prop_split_aux:NnTF}
+% \begin{macro}[aux]{\prop_split_aux:nnnn}
+% \begin{macro}[aux]{\prop_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_prop} \meta{detokenized key} \cs{q_prop}
+% \marg{value} \meta{extra argument}, effectively separating an
+% \meta{extract1} before the key in the property list and an \meta{extract2}
+% after the key.
+%
+% If the key is present in the property list, then \meta{extra argument}
+% is simply \cs{q_prop}, and \cs{prop_splot_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{extract1} \Arg{value} \Arg{extract2}.
+% In order for \meta{extract1}\meta{extract2} to be a well-formed
+% property list, \meta{extract1} has a leading and trailing \cs{q_prop},
+% retaining exactly the structure of a property list, while \meta{extract2}
+% omits the leading \cs{q_prop}.
+%
+% If the key is not there, then \meta{extra argument} is
+% |? \use_ii:nn { }|, and |\prop_split_aux:nnnn ? \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.
+% \begin{macrocode}
+\cs_set_protected:Npn \prop_split:NnTF #1#2
+ { \exp_args:NNo \prop_split_aux:NnTF #1 { \tl_to_str:n {#2} } }
+\cs_new_protected:Npn \prop_split_aux:NnTF #1#2
+ {
+ \cs_set_protected:Npn \prop_split_aux:w
+ ##1 \q_prop #2 \q_prop ##2 ##3 ##4 \q_mark ##5 \q_stop
+ { \prop_split_aux:nnnn ##3 { {##1 \q_prop } {##2} {##4} } }
+ \exp_after:wN \prop_split_aux:w #1 \q_mark
+ \q_prop #2 \q_prop { } { ? \use_ii:nn { } } \q_mark \q_stop
+ }
+\cs_new:Npn \prop_split_aux:nnnn #1#2#3#4 { #3 #2 }
+\cs_new_protected:Npn \prop_split_aux:w { }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[int]{\prop_split:Nnn}
+% The goal here is to provide a common interface for both true and false
+% branches of \cs{prop_split:NnTF}. In both cases, the code given by the
+% user will be placed in front of three brace groups, \Arg{extract1}
+% \Arg{value} \Arg{extract2}.
+% If the key was missing from the property list, then \meta{extract1}
+% is the full property list, \meta{value} is \cs{q_no_value}, and
+% \meta{extract2} is empty.
+% Otherwise, \meta{extract1} is the part of the property list before the
+% \meta{key}, and has the structure of a property list, \meta{value} is
+% the value corresponding to the \meta{key}, and \meta{extract2} (the part
+% after the \meta{key}) is missing the leading \cs{q_prop}.
+% \begin{macrocode}
+\cs_set_protected:Npn \prop_split:Nnn #1#2#3
+ {
+ \prop_split:NnTF #1 {#2}
+ {#3}
+ { \exp_args:Nno \use:n {#3} {#1} { \q_no_value } { } }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \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{macro}[aux]{\prop_del_aux: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_del:Nn #1#2
+ { \prop_split:NnTF #1 {#2} { \prop_del_aux:NNnnn \tl_set:Nn #1 } { } }
+\cs_new_protected:Npn \prop_gdel:Nn #1#2
+ { \prop_split:NnTF #1 {#2} { \prop_del_aux:NNnnn \tl_gset:Nn #1 } { } }
+\cs_new_protected:Npn \prop_del_aux:NNnnn #1#2#3#4#5
+ { #1 #2 { #3 #5 } }
+\cs_generate_variant:Nn \prop_del:Nn { NV }
+\cs_generate_variant:Nn \prop_del:Nn { c , cV }
+\cs_generate_variant:Nn \prop_gdel:Nn { NV }
+\cs_generate_variant:Nn \prop_gdel:Nn { c , cV }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \prop_get:NnN, \prop_get:NVN, \prop_get:NoN,
+% \prop_get:cnN, \prop_get:cVN, \prop_get:NoN
+% }
+% \begin{macro}[aux]{\prop_get_aux: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}.
+% \begin{macrocode}
+\cs_new_protected:Npn \prop_get:NnN #1#2#3
+ {
+ \prop_split:NnTF #1 {#2}
+ { \prop_get_aux:Nnnn #3 }
+ { \tl_set:Nn #3 { \q_no_value } }
+ }
+\cs_new_protected:Npn \prop_get_aux: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}{\prop_pop:NnN, \prop_pop:NoN, \prop_pop:cnN, \prop_pop:coN}
+% \begin{macro}{\prop_gpop:NnN, \prop_gpop:NoN, \prop_gpop:cnN, \prop_gpop:coN}
+% \begin{macro}[aux]{\prop_pop_aux: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.
+% If the key is missing, save \cs{q_no_value} in the token list.
+% \begin{macrocode}
+\cs_new_protected:Npn \prop_pop:NnN #1#2#3
+ {
+ \prop_split:NnTF #1 {#2}
+ { \prop_pop_aux:NNNnnn \tl_set:Nn #1 #3 }
+ { \tl_set:Nn #3 { \q_no_value } }
+ }
+\cs_new_protected:Npn \prop_gpop:NnN #1#2#3
+ {
+ \prop_split:NnTF #1 {#2}
+ { \prop_pop_aux:NNNnnn \tl_gset:Nn #1 #3 }
+ { \tl_set:Nn #3 { \q_no_value } }
+ }
+\cs_new_protected:Npn \prop_pop_aux: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 }
+\cs_generate_variant:Nn \prop_gpop:NnN { c , co }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \prop_put:Nnn, \prop_put:NnV, \prop_put:Nno, \prop_put:Nnx,
+% \prop_put:NVn, \prop_put:NVV, \prop_put:Non, \prop_put:Noo,
+% \prop_put:cnn, \prop_put:cnV, \prop_put:cno, \prop_put:cnx,
+% \prop_put:cVn, \prop_put:cVV, \prop_put:con, \prop_put:coo
+% }
+% \begin{macro}
+% {
+% \prop_gput:Nnn, \prop_gput:NnV, \prop_gput:Nno, \prop_gput:Nnx,
+% \prop_gput:NVn, \prop_gput:NVV, \prop_gput:Non, \prop_gput:Noo,
+% \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]{\prop_put_aux:NNnnnnn}
+% Putting a key--value pair in a property list starts by splitting
+% to remove any existing value. The property list is then
+% reconstructed with the two remaining parts |#5| and |#7| first,
+% followed by the new or updated entry.
+% \begin{macrocode}
+\cs_new_protected:Npn \prop_put:Nnn { \prop_put_aux:NNnn \tl_set:Nx }
+\cs_new_protected:Npn \prop_gput:Nnn { \prop_put_aux:NNnn \tl_gset:Nx }
+\cs_new_protected:Npn \prop_put_aux:NNnn #1#2#3#4
+ {
+ \prop_split:Nnn #2 {#3} { \prop_put_aux:NNnnnnn #1 #2 {#3} {#4} }
+ }
+\cs_new_protected:Npn \prop_put_aux:NNnnnnn #1#2#3#4#5#6#7
+ {
+ #1 #2
+ {
+ \exp_not:n { #5 #7 }
+ \tl_to_str:n {#3} \exp_not:n { \q_prop {#4} \q_prop }
+ }
+ }
+\cs_generate_variant:Nn \prop_put:Nnn
+ { NnV , Nno , Nnx , NV , NVV , No , Noo }
+\cs_generate_variant:Nn \prop_put:Nnn
+ { c , cnV , cno , cnx , cV , cVV , co , coo }
+\cs_generate_variant:Nn \prop_gput:Nnn
+ { NnV , Nno , Nnx , NV , NVV , No , Noo }
+\cs_generate_variant:Nn \prop_gput:Nnn
+ { c , cnV , cno , cnx , cV , cVV , co , coo }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\prop_put_if_new:Nnn, \prop_put_if_new:cnn}
+% \begin{macro}{\prop_gput_if_new:Nnn, \prop_gput_if_new:cnn}
+% Adding conditionally also splits. If the key is already present,
+% the three brace groups given by \cs{prop_split:NnTF} are removed.
+% If the key is new, then the value is added, being careful to
+% convert the key to a string using \cs{tl_to_str:n}.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \prop_put_if_new:Nnn
+ { \prop_put_if_new_aux:NNnn \tl_put_right:Nx }
+\cs_new_protected_nopar:Npn \prop_gput_if_new:Nnn
+ { \prop_put_if_new_aux:NNnn \tl_gput_right:Nx }
+\cs_new_protected:Npn \prop_put_if_new_aux:NNnn #1#2#3#4
+ {
+ \prop_split:NnTF #2 {#3}
+ { \use_none:nnn }
+ {
+ #1 #2
+ { \tl_to_str:n {#3} \exp_not:n { \q_prop {#4} \q_prop } }
+ }
+ }
+\cs_generate_variant:Nn \prop_put_if_new:Nnn { c }
+\cs_generate_variant:Nn \prop_gput_if_new:Nnn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Property list conditionals}
+%
+% \begin{macro}[pTF]{\prop_if_empty:N, \prop_if_empty:c}
+% The test here uses \cs{c_empty_prop} as it is not really empty!
+% \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}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[pTF]
+% {
+% \prop_if_in:Nn, \prop_if_in:NV, \prop_if_in:No,
+% \prop_if_in:cn, \prop_if_in:cV, \prop_if_in:co
+% }
+% \begin{macro}[aux]{\prop_if_in_aux:w}
+% Testing expandably if a key is in a property list
+% requires to go through the key--value pairs one by one.
+% This is rather slow, and a faster test would be
+% \begin{verbatim}
+% \prg_new_protected_conditional:Npnn \prop_if_in:Nn #1 #2
+% {
+% \prop_split:NnTF #1 {#2}
+% {
+% \prg_return_true:
+% \use_none:nnn
+% }
+% { \prg_return_false: }
+% }
+% \end{verbatim}
+% but \cs{prop_split:NnTF} is non-expandable.
+%
+% Instead, the key is compared to each key in turn using \cs{str_if_eq:nn},
+% which is expandable. The mapping is stopped using |A|, which cannot appear
+% within a key of the property list, since keys are strings.
+% 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
+% is searched for.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \prop_if_in:Nn #1#2 { p , T , F , TF }
+ {
+ \exp_last_unbraced:Noo \prop_if_in_aux:nwn
+ { \tl_to_str:n {#2} } #1
+ A \q_prop { } \q_stop
+ }
+\cs_new:Npn \prop_if_in_aux:nwn #1 \q_prop #2 \q_prop #3
+ {
+ \if_catcode:w A #2
+ \prg_return_false:
+ \exp_after:wN \use_none_delimit_by_q_stop:w
+ \fi:
+ \str_if_eq:nnT {#1} {#2}
+ {
+ \prg_return_true:
+ \use_none_delimit_by_q_stop:w
+ }
+ \prop_if_in_aux:nwn {#1}
+ }
+\cs_generate_variant:Nn \prop_if_in_p:Nn { NV , No }
+\cs_generate_variant:Nn \prop_if_in_p:Nn { c , cV , co }
+\cs_generate_variant:Nn \prop_if_in:NnT { NV , No }
+\cs_generate_variant:Nn \prop_if_in:NnT { c , cV , co }
+\cs_generate_variant:Nn \prop_if_in:NnF { NV , No }
+\cs_generate_variant:Nn \prop_if_in:NnF { c , cV , co }
+\cs_generate_variant:Nn \prop_if_in:NnTF { NV , No }
+\cs_generate_variant:Nn \prop_if_in:NnTF { c , cV , co }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Mapping to property lists}
+%
+% \begin{macro}
+% {
+% \prop_map_function:NN, \prop_map_function:Nc,
+% \prop_map_function:cN, \prop_map_function:cc
+% }
+% \begin{macro}[aux]{\prop_map_function_aux:Nwn}
+% The fastest way to do a recursion here is to use an
+% \cs{if_catcode:w} test: the keys are strings, and thus
+% cannot match the marker |A| (which has catcode \enquote{letter}).
+% \begin{macrocode}
+\cs_new_nopar:Npn \prop_map_function:NN #1#2
+ {
+ \exp_last_unbraced:NNo \prop_map_function_aux:Nwn #2
+ #1 A \q_prop { } \q_recursion_stop
+ }
+\cs_new:Npn \prop_map_function_aux:Nwn #1 \q_prop #2 \q_prop #3
+ {
+ \if_catcode:w A #2
+ \exp_after:wN \prop_map_break:
+ \fi:
+ #1 {#2} {#3}
+ \prop_map_function_aux:Nwn #1
+ }
+\cs_generate_variant:Nn \prop_map_function:NN { Nc }
+\cs_generate_variant:Nn \prop_map_function:NN { c , cc }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{variable}{\g_prop_map_inline_int}
+% A nesting counter for mapping.
+% \begin{macrocode}
+\int_new:N \g_prop_map_inline_int
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\prop_map_inline:Nn, \prop_map_inline:cn}
+% Mapping in line requires a nesting level counter.
+% \begin{macrocode}
+\cs_new_protected:Npn \prop_map_inline:Nn #1#2
+ {
+ \int_gincr:N \g_prop_map_inline_int
+ \cs_gset:cpn { prop_map_inline_ \int_use:N \g_prop_map_inline_int :nn }
+ ##1##2 {#2}
+ \prop_map_function:Nc #1
+ { prop_map_inline_ \int_use:N \g_prop_map_inline_int :nn }
+ \int_gdecr:N \g_prop_map_inline_int
+ }
+\cs_generate_variant:Nn \prop_map_inline:Nn { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\prop_map_break:}
+% Breaking the map function simply means removing everything up to
+% the \cs{q_stop} marker.
+% \begin{macrocode}
+\cs_new_eq:NN \prop_map_break: \use_none_delimit_by_q_recursion_stop:w
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\prop_map_break:n}
+% The same idea for using one set of tokens.
+% \begin{macrocode}
+\cs_new_eq:NN \prop_map_break:n \use_i_delimit_by_q_recursion_stop:nw
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Viewing property lists}
+%
+% \begin{variable}{\l_prop_show_tl}
+% Used to store the material for display.
+% \begin{macrocode}
+\tl_new:N \l_prop_show_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\prop_show:N, \prop_show:c}
+% \begin{macro}[aux]{\prop_show_aux:n}
+% \begin{macro}[aux]{\prop_show_aux:w}
+% The aim of the mapping here is to create a token list containing the
+% formatted property list. The very first item needs the new line and
+% \verb*|> | removing, which is achieved using a \texttt{w}-type auxiliary.
+% To avoid a low-level \TeX{} error if there is an empty property list, a
+% simple test is used to keep the output \enquote{clean}.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \prop_show:N #1
+ {
+ \prop_if_empty:NTF #1
+ {
+ \iow_term:x { Property~list~\token_to_str:N #1 \c_space_tl is~empty }
+ \tl_show:n { }
+ }
+ {
+ \iow_term:x
+ {
+ Property~list~\token_to_str:N #1 \c_space_tl
+ contains~the~pairs~(without~outer~braces):
+ }
+ \tl_set:Nx \l_prop_show_tl
+ { \prop_map_function:NN #1 \prop_show_aux:nn }
+ \tl_show:n \exp_after:wN \exp_after:wN \exp_after:wN
+ { \exp_after:wN \prop_show_aux:w \l_prop_show_tl }
+ }
+ }
+\cs_new:Npn \prop_show_aux:nn #1#2
+ {
+ \iow_newline: > \c_space_tl \c_space_tl
+ \iow_char:N \{ #1 \iow_char:N \}
+ \c_space_tl \c_space_tl => \c_space_tl \c_space_tl
+ \iow_char:N \{ \exp_not:n {#2} \iow_char:N \}
+ }
+\cs_new:Npn \prop_show_aux:w #1 > ~ { }
+\cs_generate_variant:Nn \prop_show:N { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Experimental functions}
+%
+% \begin{macro}[TF]{\prop_get:NnN}
+% \begin{macro}[aux]{\prop_get_aux_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.
+% \begin{macrocode}
+\prg_new_protected_conditional:Npnn \prop_get:NnN #1#2#3 { T , F , TF }
+ {
+ \prop_split:NnTF #1 {#2}
+ { \prop_get_aux_true:Nnnn #3 }
+ { \prg_return_false: }
+ }
+\cs_new_protected:Npn \prop_get_aux_true:Nnnn #1#2#3#4
+ {
+ \tl_set:Nn #1 {#3}
+ \prg_return_true:
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[TF]{\prop_pop:NnN,\prop_gpop:NnN}
+% \begin{macro}[aux]{\prop_pop_aux_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
+% list are altered. Otherwise, \cs{prg_return_true:} is used after
+% the assignments.
+% \begin{macrocode}
+\prg_new_protected_conditional:Npnn \prop_pop:NnN #1#2#3 {T,F,TF}
+ {
+ \prop_split:NnTF #1 {#2}
+ { \prop_pop_aux_true:NNNnnn \tl_set:Nn #1 #3 }
+ { \prg_return_false: }
+ }
+\prg_new_protected_conditional:Npnn \prop_gpop:NnN #1#2#3 {T,F,TF}
+ {
+ \prop_split:NnTF #1 {#2}
+ { \prop_pop_aux_true:NNNnnn \tl_gset:Nn #1 #3 }
+ { \prg_return_false: }
+ }
+\cs_new_protected:Npn \prop_pop_aux_true:NNNnnn #1#2#3#4#5#6
+ {
+ \tl_set:Nn #3 {#5}
+ #1 #2 { #4 #6 }
+ \prg_return_true:
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\prop_map_tokens:Nn}
+% \begin{macro}[aux]{\prop_map_tokens_aux:nwn}
+% The mapping grabs one key--value pair at a time, and stops when
+% reaching the marker key |A|, with catcode \enquote{letter}, which
+% cannot appear in normal keys since those are strings. The odd
+% construction |\use:n {#1}| allows |#1| to contain any token.
+% \begin{macrocode}
+\cs_new:Npn \prop_map_tokens:Nn #1#2
+ {
+ \exp_last_unbraced:Nno \prop_map_tokens_aux:nwn {#2} #1
+ A \q_prop { } \q_recursion_stop
+ }
+\cs_new:Npn \prop_map_tokens_aux:nwn #1 \q_prop #2 \q_prop #3
+ {
+ \if_catcode:w A #2
+ \exp_after:wN \prop_map_break:
+ \fi:
+ \use:n {#1} {#2} {#3}
+ \prop_map_tokens_aux:nwn {#1}
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\prop_get:Nn}
+% \begin{macro}[aux]{\prop_get_aux:nnn}
+% Getting expandably the value corresponding to a key in a property list
+% is a simple instance of mapping some tokens.
+% Map the function \cs{prop_get_aux:nnn} which takes as its three
+% arguments the \meta{key} that we are looking for, the current
+% \meta{key} and the current \meta{value}. If the \meta{keys} match,
+% the \meta{value} is returned. If none of the keys match, this expands
+% to nothing.
+% \begin{macrocode}
+\cs_new:Npn \prop_get:Nn #1 #2
+ { \prop_map_tokens:Nn #1 { \prop_get_aux:nnn {#2} } }
+\cs_new:Npn \prop_get_aux:nnn #1 #2 #3
+ { \str_if_eq:nnT {#1} {#2} { \prop_map_break:n {#3} } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Deprecated interfaces}
+%
+% Deprecated on 2011-05-27, for removal by 2011-08-31.
+%
+% \begin{macro}{\prop_display:N, \prop_display:c}
+% An older name for \cs{prop_show:N}.
+% \begin{macrocode}
+\cs_new_eq:NN \prop_display:N \prop_show:N
+\cs_new_eq:NN \prop_display:c \prop_show:c
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\prop_gget:NnN, \prop_gget:NVN, \prop_gget:cnN, \prop_gget:cVN}
+% \begin{macro}[aux]{\prop_gget_aux:Nnnn}
+% Getting globally is no longer supported: this is a conceptual change, so
+% the necessary code for the transition is provided directly.
+% \begin{macrocode}
+\cs_new_protected:Npn \prop_gget:NnN #1#2#3
+ { \prop_split:Nnn #1 {#2} { \prop_gget_aux:Nnnn #3 } }
+\cs_new_protected:Npn \prop_gget_aux:Nnnn #1#2#3#4
+ { \tl_gset:Nn #1 {#3} }
+\cs_generate_variant:Nn \prop_gget:NnN { NV }
+\cs_generate_variant:Nn \prop_gget:NnN { c , cV }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\prop_get_gdel:NnN}
+% This name seems very odd.
+% \begin{macrocode}
+\cs_new_eq:NN \prop_get_gdel:NnN \prop_gpop:NnN
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[TF]{\prop_if_in:cc}
+% A hang-over from an ancient implementation
+% \begin{macrocode}
+\cs_generate_variant:Nn \prop_if_in:NnT { cc }
+\cs_generate_variant:Nn \prop_if_in:NnF { cc }
+\cs_generate_variant:Nn \prop_if_in:NnTF { cc }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\prop_gput:ccx}
+% Another one.
+% \begin{macrocode}
+\cs_generate_variant:Nn \prop_gput:Nnn { ccx }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[pTF]
+% {\prop_if_eq:NN, \prop_if_eq:Nc, \prop_if_eq:cN, \prop_if_eq:cc}
+% These ones do no even make sense!
+% \begin{macrocode}
+\prg_new_eq_conditional:NNn \prop_if_eq:NN \tl_if_eq:NN { p , T , F , TF }
+\prg_new_eq_conditional:NNn \prop_if_eq:cN \tl_if_eq:cN { p , T , F , TF }
+\prg_new_eq_conditional:NNn \prop_if_eq:Nc \tl_if_eq:Nc { p , T , F , TF }
+\prg_new_eq_conditional:NNn \prop_if_eq:cc \tl_if_eq:cc { p , T , F , TF }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex \ No newline at end of file