diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3keyval.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3keyval.dtx | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3keyval.dtx b/Master/texmf-dist/source/latex/l3kernel/l3keyval.dtx new file mode 100644 index 00000000000..999ae7e5b08 --- /dev/null +++ b/Master/texmf-dist/source/latex/l3kernel/l3keyval.dtx @@ -0,0 +1,405 @@ +% \iffalse meta-comment +% +%% File: l3keyval.dtx Copyright (C) 2006-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: l3keyval.dtx 2478 2011-06-19 21:34:23Z joseph $ + {L3 Experimental key-value parsing} +%</driver|package> +%<*driver> +\documentclass[full]{l3doc} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \title{^^A +% The \pkg{l3keyval} package\\ Key--value parsing^^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} +% +% A key--value list is input of the form +% \begin{verbatim} +% KeyOne = ValueOne , +% KeyTwo = ValueTwo , +% KeyThree +% \end{verbatim} +% where each key--value pair is separated by a comma from the rest of +% the list, and each key--value pair does not necessarily contain an +% equals sign or a value! Processing this type of input correctly +% requires a number of careful steps, to correctly account for +% braces, spaces and the category codes of separators. +% +% This module provides the low-level machinery for processing arbitrary +% key--value lists. The \pkg{l3keys} module provides a higher-level +% interface for managing run-time settings using key--value input, +% while other parts of \LaTeX3 also use key--value input based on +% \pkg{l3keyval} (for example the \pkg{xtemplate} module). +% + %\section{Parsing key--value lists} +% +% The low-level parsing system converts a \meta{key--value list} +% into \meta{keys} and associated \meta{values}. After the parsing phase +% is completed, the resulting keys and values (or keys alone) are +% available for further processing. This is not carried out by the +% low-level parser, and so the parser requires the names of +% two functions along with the key--value list. One function is +% needed to process key--value pairs (\emph{i.e}~two arguments), +% and a second function if required for keys given without arguments +% (\emph{i.e.}~a single argument). +% +% The parser does not double |#| tokens or expand any input. The tokens +% |=| and |,| are corrected so that the parser does not \enquote{miss} +% any due to category code changes. Spaces are removed from the ends +% of the keys and values. Values which are given in braces will have +% exactly one set removed, thus +% \begin{verbatim} +% key = {value here}, +% \end{verbatim} +% and +% \begin{verbatim} +% key = value here, +% \end{verbatim} +% are treated identically. +% + %\begin{function}{\keyval_parse:NNn} +% \begin{syntax} +% \cs{keyval_parse:NNn} \meta{function1} \meta{function2} +% ~~\Arg{key--value list} +% \end{syntax} +% Parses the \meta{key--value list} into a series of \meta{keys} and +% associated \meta{values}, or keys alone (if no \meta{value} was +% given). \meta{function1} should take one argument, while +% \meta{function2} should absorb two arguments. After +% \cs{keyval_parse:NNn} has parsed the \meta{key--value list}, +% \meta{function1} will be used to process keys given with no value +% and \meta{function2} will be used to process keys given with a +% value. The order of the \meta{keys} in the \meta{key--value list} +% will be preserved. Thus +% \begin{verbatim} +% \keyval_parse:NNn \function:n \function:nn +% { key1 = value1 , key2 = value2, key3 = , key4 } +% \end{verbatim} +% will be converted into an input stream +% \begin{verbatim} +% \function:nn { key1 } { value1 } +% \function:nn { key2 } { value2 } +% \function:nn { key3 } { } +% \function:n { key4 } +% \end{verbatim} +% Note that there is a difference between an empty value (an equals +% sign followed by nothing) and a missing value (no equals sign at +% all). +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3keyval} implementation} +% +% \begin{macrocode} +%<*initex|package> +% \end{macrocode} +% +% \begin{macrocode} +%<*package> +\ProvidesExplPackage + {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} +\package_check_loaded_expl: +%</package> +% \end{macrocode} +% +% \begin{variable}{\g_keyval_level_int} +% For nesting purposes an integer is needed for the current level. +% \begin{macrocode} +\int_new:N \g_keyval_level_int +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_keyval_key_tl, \l_keyval_value_tl} +% The current key name and value. +% \begin{macrocode} +\tl_new:N \l_keyval_key_tl +\tl_new:N \l_keyval_value_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_keyval_sanitise_tl} +% \begin{variable}{\l_keyval_parse_tl} +% Token list variables for dealing with awkward category codes in the +% input. +% \begin{macrocode} +\tl_new:N \l_keyval_sanitise_tl +\tl_new:N \l_keyval_parse_tl +% \end{macrocode} +%\end{variable} +%\end{variable} +% +% \begin{macro}{\keyval_parse:n} +% The parsing function first deals with the category codes for +% |=| and |,|, so that there are no odd events. The input is then +% handed off to the element by element system. +% \begin{macrocode} +\group_begin: + \char_set_catcode_active:n { `\= } + \char_set_catcode_active:n { `\, } + \char_set_lccode:nn { `\8 } { `\= } + \char_set_lccode:nn { `\9 } { `\, } +\tl_to_lowercase:n + { + \group_end: + \cs_new_protected:Npn \keyval_parse:n #1 + { + \group_begin: + \tl_clear:N \l_keyval_sanitise_tl + \tl_set:Nn \l_keyval_sanitise_tl {#1} + \tl_replace_all_in:Nnn \l_keyval_sanitise_tl { = } { 8 } + \tl_replace_all_in:Nnn \l_keyval_sanitise_tl { , } { 9 } + \tl_clear:N \l_keyval_parse_tl + \exp_after:wN \keyval_parse_elt:w \exp_after:wN + \q_no_value \l_keyval_sanitise_tl 9 \q_nil 9 + \exp_after:wN \group_end: + \l_keyval_parse_tl + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\keyval_parse_elt:w} +% Each item to be parsed will have \cs{q_no_value} added to the front. +% Hence the blank test here can always be used to find a totally +% empty argument. If this is the case, the system loops round. If there +% is something to parse, there is a check for the \cs{q_nil} marker +% and if not a hand-off. +% \begin{macrocode} +\cs_new_protected:Npn \keyval_parse_elt:w #1 , + { + \tl_if_blank:oTF { \use_none:n #1 } + { \keyval_parse_elt:w \q_no_value } + { + \quark_if_nil:oF { \use_ii:nn #1 } + { + \keyval_split_key_value:w #1 = = \q_stop + \keyval_parse_elt:w \q_no_value + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\keyval_split_key_value:w} +% \begin{macro}[aux]{\keyval_split_key_value_aux:wTF} +% The key and value are handled separately. First the key is grabbed and +% saved as \cs{l_keyval_key_tl}. Then a check is need to see if there is +% a value at all: if not then the key name is simply added to the output. +% If there is a value then there is a check to ensure that there was +% only one |=| in the input (remembering some extra ones are around at +% the moment to prevent errors). All being well, there is an +% hand-off to find the value: the \cs{q_nil} is there to prevent loss +% of braces. +% \begin{macrocode} +\cs_new_protected:Npn \keyval_split_key_value:w #1 = #2 \q_stop + { + \keyval_split_key:w #1 \q_stop + \str_if_eq:nnTF {#2} { = } + { + \tl_put_right:Nx \l_keyval_parse_tl + { + \exp_not:c { keyval_key_no_value_elt_ \int_use:N \g_keyval_level_int :n } + { \exp_not:o \l_keyval_key_tl } + } + } + { + \keyval_split_key_value_aux:wTF #2 \q_no_value \q_stop + { \keyval_split_value:w \q_nil #2 } + { \msg_kernel_error:nn { keyval } { misplaced-equals-sign } } + } + } +\cs_new:Npn \keyval_split_key_value_aux:wTF #1 = #2#3 \q_stop + { \tl_if_head_eq_meaning:nNTF {#3} \q_no_value } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\keyval_split_key:w} +% \begin{macro}{\keyval_remove_spaces:w} +% \begin{macro}[aux]{\keyval_split_key_aux:w} +% \begin{macro}[aux]{\keyval_remove_spaces_aux:w} +% The aim here is to remove spaces and also exactly one set of braces. +% The spaces are trimmed off from each end using a \enquote{funny} +% |Q|, which will never turn up in normal use. The idea is that +% the \texttt{f}-type expansion will stop if it finds an unexpandable +% token or a space, and will gobble the space. To avoid expanding +% anything else, the \cs{exp_not:N} works by ensuring that the first +% non-space token in the setting will stop the \texttt{f}-type +% expansion. The \cs{use_none:n} is needed to remove the leading +% quark, while the second setting of \cs{l_keyval_key_tl} +% removes exactly one set of braces. +% \begin{macrocode} +\group_begin: + \char_set_catcode_math_toggle:n { `\Q } + \cs_new_protected:Npn \keyval_split_key:w #1 \q_stop + { + \exp_args:NNf \tl_set:Nn \l_keyval_key_tl + { + \exp_after:wN \keyval_remove_spaces:w \exp_after:wN + \exp_not:N \use_none:n #1 Q ~ Q + } + \tl_set:Nx \l_keyval_key_tl + { \exp_after:wN \keyval_split_key_aux:w \l_keyval_key_tl \q_stop } + } + \cs_gset:Npn \keyval_split_key_aux:w #1 \q_stop { \exp_not:n {#1} } + \cs_gset:Npn \keyval_remove_spaces:w #1 ~ Q { \keyval_remove_spaces_aux:w #1 Q } + \cs_gset:Npn \keyval_remove_spaces_aux:w #1 Q #2 {#1} +\group_end: +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\keyval_split_value:w} +% Here the value has to be separated from the equals signs and the +% leading \cs{q_nil} added in to keep the brace levels. Fist the +% processing function can be added to the output list. If there is no +% value, setting \cs{l_keyval_value_tl} with three groups removed will +% leave nothing at all, and so an empty group can be added to the +% parsed list. On the other hand, if the value is entirely contained +% within a set of braces then \cs{l_keyval_value_tl} will contain +% \cs{q_nil} only. In that case, strip off the leading quark using +% \cs{use_ii:nnn}, which also deals with any spaces. +% \begin{macrocode} +\cs_new_protected:Npn \keyval_split_value:w #1 = = + { + \tl_put_right:Nx \l_keyval_parse_tl + { + \exp_not:c { keyval_key_value_elt_ \int_use:N \g_keyval_level_int :nn } + { \exp_not:o \l_keyval_key_tl } + } + \tl_set:Nx \l_keyval_value_tl { \exp_not:o { \use_none:nnn #1 \q_nil \q_nil } } + \tl_if_empty:NTF \l_keyval_value_tl + { \tl_put_right:Nn \l_keyval_parse_tl { { } } } + { + \quark_if_nil:NTF \l_keyval_value_tl + { + \tl_put_right:Nx \l_keyval_parse_tl + { { \exp_not:o { \use_ii:nnn #1 \q_nil } } } + } + { \keyval_split_value_aux:w #1 \q_stop } + } + } +% \end{macrocode} +% A similar idea to the key code: remove the spaces from each end and +% deal with one set of braces. +% \begin{macrocode} +\group_begin: + \char_set_catcode_math_toggle:n { `\Q } + \cs_new_protected:Npn \keyval_split_value_aux:w \q_nil #1 \q_stop + { + \exp_args:NNf \tl_set:Nn \l_keyval_value_tl + { \keyval_remove_spaces:w \exp_not:N #1 Q ~ Q } + \tl_put_right:Nx \l_keyval_parse_tl { { \exp_not:o \l_keyval_value_tl } } + } +\group_end: +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\keyval_parse:NNn} +% The outer parsing routine just sets up the processing functions and +% hands off. +% \begin{macrocode} +\cs_new_protected:Npn \keyval_parse:NNn #1#2#3 + { + \int_gincr:N \g_keyval_level_int + \cs_gset_eq:cN { keyval_key_no_value_elt_ \int_use:N \g_keyval_level_int :n } #1 + \cs_gset_eq:cN { keyval_key_value_elt_ \int_use:N \g_keyval_level_int :nn } #2 + \keyval_parse:n {#3} + \int_gdecr:N \g_keyval_level_int + } +% \end{macrocode} +% \end{macro} +% +% One message for the low level parsing system. +% \begin{macrocode} +\msg_kernel_new:nnnn { keyval } { misplaced-equals-sign } + { Misplaced~equals~sign~in~key-value~input~\msg_line_number: } + { + LaTeX~is~attempting~to~parse~some~key-value~input~but~found~ + two~equals~signs~not~separated~by~a~comma. + } +% \end{macrocode} +% +% \subsection{Deprecated functions} +% +% Deprecated on 2011-05-27, for removal by 2011-08-31. +% +% \begin{macro}{\KV_process_space_removal_sanitize:NNn} +% \begin{macro}{\KV_process_space_removal_no_sanitize:NNn} +% \begin{macro}{\KV_process_no_space_removal_no_sanitize:NNn} +% There is just one function for this now. +% \begin{macrocode} +\cs_new_eq:NN \KV_process_space_removal_sanitize:NNn \keyval_parse:NNn +\cs_new_eq:NN \KV_process_space_removal_no_sanitize:NNn \keyval_parse:NNn +\cs_new_eq:NN \KV_process_no_space_removal_no_sanitize:NNn \keyval_parse:NNn +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +%</initex|package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex |