summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/expl3/l3keyval.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/expl3/l3keyval.dtx')
-rw-r--r--Master/texmf-dist/source/latex/expl3/l3keyval.dtx666
1 files changed, 666 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/expl3/l3keyval.dtx b/Master/texmf-dist/source/latex/expl3/l3keyval.dtx
new file mode 100644
index 00000000000..8848946602a
--- /dev/null
+++ b/Master/texmf-dist/source/latex/expl3/l3keyval.dtx
@@ -0,0 +1,666 @@
+% \iffalse
+%% File: l3keyval.dtx Copyright (C) 2006 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/cgi-bin/cvsweb.cgi/
+%%
+%% 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 LaTeX Project Team.
+%%
+%% -----------------------------------------------------------------------
+%<package>\RequirePackage{l3names}
+%<*dtx>
+%\fi
+\def\GetIdInfo$Id: #1.dtx #2 #3-#4-#5 #6 #7$#8{%
+ \def\fileversion{#2}%
+ \def\filedate{#3/#4/#5}%
+ \ProvidesFile{#1.dtx}[#3/#4/#5 v#2 #8]%
+}
+%\iffalse
+%</dtx>
+%\fi
+\GetIdInfo$Id: l3keyval.dtx 573 2006-08-21 20:59:37Z morten $
+ {L3 Experimental keyval processing}
+% \iffalse
+%<*driver>
+\documentclass{l3doc}
+
+\begin{document}
+\DocInput{l3keyval.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{The \textsf{l3keyval} package\thanks{This file
+% has version number \fileversion, last
+% revised \filedate.}\\
+% Key-value parsing}
+% \author{\Team}
+% \date{\filedate}
+% \maketitle
+%
+% \section{Introduction}
+%
+% Currently, this module only provides functions for extracting keys
+% and values from a list. How this information is used is up to the
+% programmer.
+%
+% A \meta{keyval list} is a list consisting of
+% \begin{verbatim}
+% key 1 = value 1 ,
+% key 2 ,
+% key 3 = value 3 ,
+% \end{verbatim}
+%
+% The function names for retrieving the keys and values are long but
+% explain what they do. All these functions start with the name
+% |\KV_parse_|. If a value is surrounded by braces, one level (and
+% only one) is removed from the value. This is useful if you need to
+% input a value which contains |=| or |,|. There are two primary
+% actions we can take on a \meta{keyval list}.
+% \begin{itemize}
+% \item A \meta{keyval list} can be sanitized so that top level active
+% commas or equal signs are converted into catcode 12. When
+% declaring templates in the preamble one can probably safely assume
+% that there are no active commas or equals; these things should
+% only be active in the document. The name for this is either
+% |no_sanitize| or |sanitize|.
+% \item Spaces on either side of a key or value can be trimmed. When
+% using the \LaTeX3 programming interface, spaces are automatically
+% ignored so there it would be a waste of time to search for extra
+% spaces since there would be none. At the document level however,
+% spaces must be removed. The name for this is either
+% |no_space_removal| or |space_removal|. Note that when
+% |space_removal| is called you get an additional option where you
+% can decide if one level of braces should be stripped from the key
+% and/or value; see the description of the boolean
+% |\l_KV_remove_one_level_of_braces_bool| for details.
+% \end{itemize}
+%
+% During the parsing process, keys or values are not expanded and no
+% |#|s are doubled. When the parsing process is over, the keys and
+% values are executed in the form
+% \begin{quote}
+% "\KV_key_value_elt:nn{key 1}{value 1}" \\
+% "\KV_key_no_value_elt:n{key 2}" \\
+% "\KV_key_value_elt:nn{key 3}{value 3}"
+% \end{quote}
+% It is up to the programmer to provide a suitable definition of these
+% two functions before starting the parsing process.
+%
+%
+% \subsection{Functions}
+%
+%
+%
+%
+% \begin{function}{
+% \KV_parse_no_space_removal_no_sanitize:n |
+% }
+% \begin{syntax}
+% "\KV_parse_no_space_removal_no_sanitize:n" "{"<keyval list>"}"
+% \end{syntax}
+% Parses the keys and values literally. For use when spaces are
+% ignored and |=| and |,| have normal catcodes.
+% \end{function}
+%
+% \begin{function}{
+% \KV_parse_space_removal_no_sanitize:n |
+% }
+% \begin{syntax}
+% "\KV_parse_space_removal_no_sanitize:n" "{"<keyval list>"}"
+% \end{syntax}
+% As above but also removes spaces around keys and values. For use
+% when spaces are not ignored.
+% \end{function}
+%
+% \begin{function}{
+% \KV_parse_space_removal_sanitize:n |
+% }
+% \begin{syntax}
+% "\KV_parse_space_removal_sanitize:n" "{"<keyval list>"}"
+% \end{syntax}
+% As above but additionally also replaces top-level active |=| and
+% |,| with harmless versions.
+% \end{function}
+%
+% \begin{variable}{
+% \l_KV_remove_one_level_of_braces_bool |
+% }
+% \begin{syntax}
+% \end{syntax}
+% This boolean controls whether or not one level of braces is
+% stripped from the key and value. The default value for this
+% boolean is \meta{true} so that exactly one level of braces is
+% stripped. For certain applications it is desirable to keep the
+% braces in which case the programmer just has to set the boolean
+% false temporarily. Setting this boolean has no effect when you
+% call the |no_space_removal| functions since not stripping braces
+% is a rare request and would clutter the otherwise elegant code of
+% the |no_space_removal| functions for very little gain. If you need
+% to preserve braces choose the slower |space_removal| functions.
+% \end{variable}
+%
+% \begin{function}{
+% \KV_key_no_value_elt:n |
+% \KV_key_value_elt:nn |
+% }
+% \begin{syntax}
+% "\KV_key_no_value_elt:n" "{"<key>"}" \\
+% "\KV_key_value_elt:n" "{"<key>"}" "{"<value>"}"
+% \end{syntax}
+% Functions returned by the |\KV_parse_| functions. The default
+% definition of these two functions is an error message!
+% \end{function}
+%
+%
+% \StopEventually{}
+%
+% \section{Implementation}
+%
+%
+% We start by ensuring that the required packages are loaded.
+% \begin{macrocode}
+%<*package>
+\RequirePackage{l3quark}
+\RequirePackage{l3toks}
+\RequirePackage{l3int}
+\RequirePackage{l3token}
+%</package>
+%<*initex|package>
+% \end{macrocode}
+%
+%
+%
+%
+% \begin{macro}{\l_KV_tmpa_tlp}
+% \begin{macro}{\l_KV_tmpb_tlp}
+% \begin{macro}{\c_KV_single_equal_sign_tlp}
+% Various useful things.
+% \begin{macrocode}
+\tlp_new:Nn\l_KV_tmpa_tlp{}
+\tlp_new:Nn\l_KV_tmpb_tlp{}
+\tlp_new:Nn \c_KV_single_equal_sign_tlp{=}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\l_KV_parse_toks}
+% \begin{macro}{\l_KV_currkey_toks}
+% \begin{macro}{\l_KV_currval_toks}
+% Some more useful things.
+% \begin{macrocode}
+\toks_new:N \l_KV_parse_toks
+\toks_new:N \l_KV_currkey_toks
+\toks_new:N \l_KV_currval_toks
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\l_KV_remove_one_level_of_braces_bool}
+% A boolean to control
+% \begin{macrocode}
+\bool_new:N \l_KV_remove_one_level_of_braces_bool
+\bool_set_true:N \l_KV_remove_one_level_of_braces_bool
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\KV_sanitize_outerlevel_active_equals:N}
+% \begin{macro}{\KV_sanitize_outerlevel_active_commas:N}
+% Some functions for sanitizing top level equals and commas. Replace
+% |=|$\sb{13}$ and |,|$\sb{13}$ with |=|$\sb{12}$ and |,|$\sb{12}$
+% resp.
+% \begin{macrocode}
+\group_begin:
+\char_set_catcode:nn{`\=}{13}
+\char_set_catcode:nn{`\,}{13}
+\char_set_lccode:nn{`\8}{`\=}
+\char_set_lccode:nn{`\9}{`\,}
+\tlist_to_lowercase:n{\group_end:
+\def_new:Npn \KV_sanitize_outerlevel_active_equals:N #1{
+ \tlp_replace_all_in:Nnn #1 = 8
+}
+\def_new:Npn \KV_sanitize_outerlevel_active_commas:N #1{
+ \tlp_replace_all_in:Nnn #1 , 9
+}
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+%
+%
+%
+% \begin{macro}{\KV_remove_surrounding_spaces:nw}
+% \begin{macro}{\KV_remove_surrounding_spaces_auxi:w}
+% \begin{macro}{\KV_remove_surrounding_spaces_auxii:w}
+% \begin{macro}{\KV_set_key_element:w}
+% \begin{macro}{\KV_set_value_element:w}
+% The macro |\KV_remove_surrounding_spaces:Nw| removes a possible
+% leading space plus a possible ending space from its second
+% argument and stores it in the token register |#1|.
+%
+% Based on Around the Bend No.~15 but with some enhancements. For
+% instance, this definition is purely expandable.
+%
+% We use a funny token |Q|$\sb3$ as a delimiter.
+% \begin{macrocode}
+\group_begin:
+\char_set_catcode:nn{`\Q}{3}
+% \end{macrocode}
+% \begin{macrocode}
+\gdef_long_new:Npn\KV_remove_surrounding_spaces:nw#1#2\q_nil{
+% \end{macrocode}
+% The idea in this processing is to use a Q with strange catcode to
+% remove a trailing space. But first, how to get this expansion going?
+%
+% If you have read the fine print in the \textsf{l3expan} module,
+% you'll know that the |f| type expansion will expand until the first
+% non-expandable token is seen and if this token is a space, it will
+% be gobbled. Sounds useful for removing a leading space but we also
+% need to make sure that it does nothing but removing that space!
+% Therefore we prepend the argument to be trimmed with an
+% |\exp_not:N|. Now why is that? |\exp_not:N| in itself is an
+% expandable command so will allow the |f| expansion to continue. If
+% the first token in the argument to be trimmed is a space, it will be
+% gobbled and the expansion stop. If the first token isn't a space,
+% the |\exp_not:N| turns it temporarily into |\scan_stop:| which is
+% unexpandable. The processing stops but the token following directly
+% after |\exp_not:N| is now back to normal.
+%
+% The function here allows you to insert arbitrary functions in the
+% first argument but they should all be with an |f| type
+% expansion. For the application in this module, we use
+% |\toks_set:Nf|.
+%
+% Once the expansion has been kick-started, we apply
+% |\KV_remove_surrounding_spaces_auxi:w| to the replacement text of
+% |#2|, adding a leading |\exp_not:N|. Note that no braces are
+% stripped off of the original argument.
+% \begin{macrocode}
+ #1{\KV_remove_surrounding_spaces_auxi:w \exp_not:N#2Q~Q}
+}
+% \end{macrocode}
+% |\KV_remove_surrounding_spaces_auxi:w| removes a trailing space if
+% present, then calls |\KV_remove_surrounding_spaces_auxii:w| to clean
+% up any leftover bizarre Qs. In order for
+% |\KV_remove_surrounding_spaces_auxii:w| to work properly we need to
+% put back a Q first.
+% \begin{macrocode}
+\gdef_long_new:Npn\KV_remove_surrounding_spaces_auxi:w#1~Q{
+ \KV_remove_surrounding_spaces_auxii:w #1 Q
+}
+% \end{macrocode}
+% Now all that is left to do is remove a leading space which should be
+% taken care of by the function used to initiate the expansion. Simply
+% return the argument before the funny Q.
+% \begin{macrocode}
+\gdef_long_new:Npn\KV_remove_surrounding_spaces_auxii:w#1Q#2{#1}
+% \end{macrocode}
+% Here are some specialized versions of the above. They do exactly
+% what we want in one go. First trim spaces from the value and then
+% put the result surrounded in braces onto |\l_KV_parse_toks|.
+% \begin{macrocode}
+\gdef_long_new:Npn\KV_add_value_element:w\q_stop#1\q_nil{
+ \toks_set:Nf\l_KV_currval_toks {
+ \KV_remove_surrounding_spaces_auxi:w \exp_not:N#1Q~Q
+ }
+ \toks_put_right:No\l_KV_parse_toks{
+ \exp_after:NN {\toks_use:N \l_KV_currval_toks}
+ }
+}
+% \end{macrocode}
+% When storing the key we firstly remove spaces plus the prepended
+% |\q_no_value|.
+% \begin{macrocode}
+\gdef_long_new:Npn\KV_set_key_element:w#1\q_nil{
+ \toks_set:Nf\l_KV_currkey_toks
+ {
+ \exp_after:NN\KV_remove_surrounding_spaces_auxi:w
+ \exp_after:NN\exp_not:N\use_none:n #1Q~Q
+ }
+% \end{macrocode}
+% Afterwards we gobble an extra level of braces if that's what we are
+% asked to do.
+% \begin{macrocode}
+ \bool_if:NT \l_KV_remove_one_level_of_braces_bool
+ {
+ \toks_set:Nd \l_KV_currkey_toks{
+ \exp_after:NN \KV_add_element_aux:w
+ \toks_use:N \l_KV_currkey_toks \q_nil
+ }
+ }
+}
+\group_end:
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\KV_add_element_aux:w}
+% A helper function for fixing braces around keys and values.
+% \begin{macrocode}
+\def_long_new:Npn \KV_add_element_aux:w#1\q_nil{#1}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% Parse a list of keyvals, put them into list form with entries like
+% |\KV_key_no_value_elt:n{key1}| and |\KV_key_value_elt:nn{key2}{val2}|.
+%
+% \begin{macro}{\KV_parse_sanitize_aux:n}
+% The slow parsing algorithm sanitizes active commas and equal signs
+% at the top level first. Then uses |#1| as inspector of each
+% element in the comma list.
+% \begin{macrocode}
+\def_long_new:Npn \KV_parse_sanitize_aux:n #1{
+ \group_begin:
+ \toks_clear:N \l_KV_parse_toks
+ \tlp_set:Nx\l_KV_tmpa_tlp{\exp_not:n{#1}}
+ \KV_sanitize_outerlevel_active_equals:N\l_KV_tmpa_tlp
+ \KV_sanitize_outerlevel_active_commas:N\l_KV_tmpa_tlp
+ \exp_after:NN \KV_parse_elt:w \exp_after:NN\q_no_value \l_KV_tmpa_tlp,\q_nil,
+% \end{macrocode}
+% We evaluate the parsed keys and values outside the group so the
+% token register is restored to its previous value.
+% \begin{macrocode}
+ \exp_after:NN\group_end:
+ \toks_use:N \l_KV_parse_toks
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\KV_parse_no_sanitize_aux:n}
+% Like above but we don't waste time sanitizing. This is probably
+% the one we will use for preamble parsing where catcodes of |=| and
+% |,| are as expected!
+% \begin{macrocode}
+\def_long_new:Npn \KV_parse_no_sanitize_aux:n #1{
+ \group_begin:
+ \toks_clear:N \l_KV_parse_toks
+ \KV_parse_elt:w \q_no_value #1,\q_nil,
+ \exp_after:NN\group_end:
+ \toks_use:N \l_KV_parse_toks
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\KV_parse_elt:w}
+% This function will always have a |\q_no_value| stuffed in as the
+% rightmost token in |#1|. In case there was a blank entry in the
+% comma separated list we just run it again. The |\use_none:n| makes
+% sure to gobble the quark |\q_no_value|. A similar test is made to
+% check if we hit the end of the recursion.
+% \begin{macrocode}
+\def_long:Npn \KV_parse_elt:w #1,{
+ \tlist_if_blank:oTF{\use_none:n #1}
+ { \KV_parse_elt:w \q_no_value }
+ {
+ \quark_if_nil:oF {\use_arg_ii:nn #1 }
+% \end{macrocode}
+% If we made it to here we can start parsing the key and value. When
+% done try, try again.
+% \begin{macrocode}
+ {
+ \KV_split_key_value_current:w #1==\q_nil
+ \KV_parse_elt:w \q_no_value
+ }
+ }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\KV_split_key_value_current:w}
+% The function called to split the keys and values.
+% \begin{macrocode}
+\let_new:NN \KV_split_key_value_current:w \ERROR
+% \end{macrocode}
+% \end{macro}
+%
+% We provide two functions for splitting keys and values. The reason
+% being that most of the time, we should probably be in the special
+% coding regime where spaces are ignored. Hence it makes no sense to
+% spend time searching for extra space tokens and we can do the
+% settings directly. When comparing these two versions (neither doing
+% any sanitizing) the |no_space_removal| version is more than 40\%
+% faster than |space_removal|.
+%
+% It is up to functions like |\DeclareTemplate| to check which catcode
+% regime is active and then pick up the version best suited for it.
+%
+%
+%
+% \begin{macro}{\KV_split_key_value_space_removal:w}
+% \begin{macro}{\KV_split_key_value_space_removal_detect_error:wTF}
+% \begin{macro}{\KV_split_key_value_space_removal_aux:w}
+% The code below removes extraneous spaces around the keys and
+% values plus one set of braces around the entire value.
+%
+% Unlike the version to be used when spaces are ignored, this one
+% only grabs the key which is everything up to the first = and save
+% the rest for closer inspection. Reason is that if a user has
+% entered |mykey={{myval}},| then the outer braces have already been
+% removed before we even look at what might come after the key. So
+% this is slightly more tedious (but only slightly) but at least it
+% always removes only one level of braces.
+% \begin{macrocode}
+\def_long_new:Npn \KV_split_key_value_space_removal:w #1 = #2\q_nil{
+% \end{macrocode}
+% First grab the key.
+% \begin{macrocode}
+ \KV_set_key_element:w#1\q_nil
+% \end{macrocode}
+% Then we start checking. If only a key was entered, |#2| contains
+% |=| and nothing else, so we test for that first.
+% \begin{macrocode}
+ \tlp_set:Nx\l_KV_tmpa_tlp{\exp_not:n{#2}}
+ \tlp_if_eq:NNTF\l_KV_tmpa_tlp\c_KV_single_equal_sign_tlp
+% \end{macrocode}
+% Then we just insert the default key.
+% \begin{macrocode}
+ {
+ \toks_put_right:No\l_KV_parse_toks{
+ \exp_after:NN \KV_key_no_value_elt:n
+ \exp_after:NN {\toks_use:N\l_KV_currkey_toks}
+ }
+ }
+% \end{macrocode}
+% Otherwise we must take a closer look at what is left. The remainder
+% of the original list up to the comma is now stored in |#2| plus an
+% additional |==|, which wasn't gobbled during the initial reading of
+% arguments. If there is an error then we can see at least one more
+% |=| so we call an auxiliary function to check for this.
+% \begin{macrocode}
+ {
+ \KV_split_key_value_space_removal_detect_error:wTF#2\q_no_value\q_nil
+ {\KV_split_key_value_space_removal_aux:w \q_stop #2}
+ {\ERROR}
+ }
+}
+% \end{macrocode}
+% The error test.
+% \begin{macrocode}
+\def_long_new:Npn
+ \KV_split_key_value_space_removal_detect_error:wTF#1=#2#3\q_nil{
+ \tlist_if_head_eq_meaning:nNTF{#3}\q_no_value
+}
+% \end{macrocode}
+% Now we can start extracting the value. Recall that |#1| here starts
+% with |\q_stop| so all braces are still there! First we try to see
+% how much is left if we gobble three brace groups from |#1|. If |#1|
+% is empty or blank, all three quarks are gobbled. If |#1| consists of
+% exactly one token or brace group, only the latter quark is left.
+% \begin{macrocode}
+\def_long_new:Npn \KV_val_preserve_braces:NnN #1#2#3{{#2}}
+\def_long_new:Npn\KV_split_key_value_space_removal_aux:w #1=={
+ \tlp_set:Nx\l_KV_tmpa_tlp{\exp_not:o{\use_none:nnn#1\q_nil\q_nil}}
+ \toks_put_right:No\l_KV_parse_toks{
+ \exp_after:NN \KV_key_value_elt:nn
+ \exp_after:NN {\toks_use:N\l_KV_currkey_toks}
+ }
+% \end{macrocode}
+% If there a blank space or nothing at all, |\l_KV_tmpa_tlp| is now
+% completely empty.
+% \begin{macrocode}
+ \tlp_if_empty:NTF\l_KV_tmpa_tlp
+% \end{macrocode}
+% We just put an empty value on the stack.
+% \begin{macrocode}
+ { \toks_put_right:Nn\l_KV_parse_toks{{}} }
+ {
+% \end{macrocode}
+% If there was exactly one brace group or token in |#1|,
+% |\l_KV_tmpa_tlp| is now equal to |\q_nil|. Then we can just pick it
+% up as the second argument of |#1|. This will also take care of any
+% spaces which might surround it.
+% \begin{macrocode}
+ \quark_if_nil:NTF\l_KV_tmpa_tlp
+ {
+ \bool_if:NTF \l_KV_remove_one_level_of_braces_bool
+ {
+ \toks_put_right:No\l_KV_parse_toks{
+ \exp_after:NN{\use_arg_ii:nnn #1\q_nil}
+ }
+ }
+ {
+ \toks_put_right:No\l_KV_parse_toks{
+ \exp_after:NN{\KV_val_preserve_braces:NnN #1\q_nil}
+ }
+ }
+ }
+% \end{macrocode}
+% Otherwise we grab the value.
+% \begin{macrocode}
+ { \KV_add_value_element:w #1\q_nil }
+ }
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\KV_split_key_value_no_space_removal:w}
+% This version is for when in the special coding regime where spaces
+% are ignored so there is no need to do any fancy space hacks,
+% however fun they may be. Since there are no spaces, a set of
+% braces around a value is automatically stripped by \TeX.
+% \begin{macrocode}
+\def_long_new:Npn \KV_split_key_value_no_space_removal:w #1#2=#3=#4\q_nil{
+ \tlp_set:Nn\l_KV_tmpa_tlp{#4}
+ \tlp_if_empty:NTF \l_KV_tmpa_tlp
+ {
+ \toks_put_right:Nn\l_KV_parse_toks{\KV_key_no_value_elt:n{#2}}
+ }
+ {
+ \tlp_if_eq:NNTF\c_KV_single_equal_sign_tlp\l_KV_tmpa_tlp
+ {
+ \toks_put_right:Nn\l_KV_parse_toks{\KV_key_value_elt:nn{#2}{#3}}
+ }
+ {\ERROR}
+ }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\KV_key_no_value_elt:n}
+% \begin{macro}{\KV_key_value_elt:nn}
+% \begin{macrocode}
+\def_long_new:Npn \KV_key_no_value_elt:n #1{\ERROR}
+\def_long_new:Npn \KV_key_value_elt:nn #1#2{\ERROR}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+%
+%
+% \begin{macro}{\KV_parse_no_space_removal_no_sanitize:n}
+% Finally we can put all the things
+% together. |\KV_parse_no_space_removal_no_sanitize:n| is the
+% version that disallows unmatched conditional and does no space
+% removal.
+% \begin{macrocode}
+\def_new:Npn \KV_parse_no_space_removal_no_sanitize:n {
+ \let:NN \KV_split_key_value_current:w \KV_split_key_value_no_space_removal:w
+ \KV_parse_no_sanitize_aux:n
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\KV_parse_space_removal_sanitize:n}
+% \begin{macro}{\KV_parse_space_removal_no_sanitize:n}
+% The other varieties can be defined in a similar manner. For the
+% version needed at the document level, we can use this one.
+% \begin{macrocode}
+\def_new:Npn \KV_parse_space_removal_sanitize:n {
+ \let:NN \KV_split_key_value_current:w \KV_split_key_value_space_removal:w
+ \KV_parse_sanitize_aux:n
+}
+% \end{macrocode}
+% For preamble use by the non-programmer this is probably best.
+% \begin{macrocode}
+\def_new:Npn \KV_parse_space_removal_no_sanitize:n {
+ \let:NN \KV_split_key_value_current:w \KV_split_key_value_space_removal:w
+ \KV_parse_no_sanitize_aux:n
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+% \begin{macrocode}
+%</initex|package>
+%<*showmemory>
+\showMemUsage
+%</showmemory>
+% \end{macrocode}
+%
+% \endinput
+%
+% $Log$
+% Revision 1.4 2006/07/25 22:38:58 morten
+% Removed spurious \exp_after:NN in \KV_add_value_element:w. Sigh.
+%
+% Revision 1.3 2006/07/25 22:34:03 morten
+% Fixed silly bug in \KV_set_key_element:w plus clean-up of code
+%
+% Revision 1.2 2006/07/25 16:21:30 morten
+% Allow values to contain unmatched conditionals such as `val
+% \fi:'. Provide option to not strip any braces at all.
+%
+% Revision 1.1 2006/01/27 10:14:24 morten
+% Initial version of keyval parser
+%