diff options
author | Karl Berry <karl@freefriends.org> | 2009-06-11 00:13:25 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2009-06-11 00:13:25 +0000 |
commit | a9f41a29daefaf04b27040f25cd0f63f41d290a6 (patch) | |
tree | bb3b723d64aa7cd49b7dc9a24de50804295b4606 | |
parent | b5132ffc519f2695644d078951baf6a558eea289 (diff) |
new latex3 package keys3 (10jun09)
git-svn-id: svn://tug.org/texlive/trunk@13703 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r-- | Master/texmf-dist/doc/latex/keys3/README | 38 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/keys3/keys3-test.tex | 394 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/keys3/keys3.pdf | bin | 0 -> 444041 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/keys3/keys3opts2.pdf | bin | 0 -> 313237 bytes | |||
-rw-r--r-- | Master/texmf-dist/source/latex/keys3/keys3.dtx | 2267 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/keys3/keys3.ins | 89 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/keys3/keys3opts2.dtx | 256 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/keys3/keys3opts2.ins | 89 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/keys3/keys3.sty | 686 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/keys3/keys3opts2.sty | 90 | ||||
-rwxr-xr-x | Master/tlpkg/bin/tlpkg-ctan-check | 3 | ||||
-rw-r--r-- | Master/tlpkg/tlpsrc/collection-latex3.tlpsrc | 1 | ||||
-rw-r--r-- | Master/tlpkg/tlpsrc/keys3.tlpsrc | 0 |
13 files changed, 3912 insertions, 1 deletions
diff --git a/Master/texmf-dist/doc/latex/keys3/README b/Master/texmf-dist/doc/latex/keys3/README new file mode 100644 index 00000000000..b79a089d7dc --- /dev/null +++ b/Master/texmf-dist/doc/latex/keys3/README @@ -0,0 +1,38 @@ +--------------------------------------------------------------- +The keys3 package --- Key management for LaTeX3 +Maintained by Joseph Wright +E-mail: joseph.wright@morningstar2.co.uk +Released under the LaTeX Project Public License v1.3c or later +See http://www.latex-project.org/lppl.txt +--------------------------------------------------------------- + +The keys3 package is an experimental implementation of key +management for LaTeX3. The entire package is written in +expl3 code rather than in traditional TeX/LaTeX. The key +module used by keys3 is based on that introduced by the +pgfkeys package from the pgf/TiKZ bundle. Keys are thus +addressed in a path-like manner, and are controlled by key +properties: + +/module/key/.code:n = <code>, +/module/key/.value_required:, +/module/key = <value> + +The keys3 package is intended as a method for testing how key +management might be implemented in LaTeX3. Both the methods +used inside the package and the interface provided are intended +to be discussed. Feedback is welcomed either by e-mail +(joseph.wright@morningstar2.co.uk) or at the package website +(http://keys3.berlios.de). + +The experimental nature of keys3 and the underlying expl3 +system means that it should not be used in production +documents. However, programmers testing expl3, or keen to work +on improved key management systems, are encouraged to try the +package and provide feedback. + +keys3 is *not* an official LaTeX3 team package. Whether any of +the ideas explored here will be taken up by the team is +therefore unknown. However, the keys3 package should provide +ideas on what needs to be available for key management and how +it can be implemented. diff --git a/Master/texmf-dist/doc/latex/keys3/keys3-test.tex b/Master/texmf-dist/doc/latex/keys3/keys3-test.tex new file mode 100644 index 00000000000..2715d0f8a91 --- /dev/null +++ b/Master/texmf-dist/doc/latex/keys3/keys3-test.tex @@ -0,0 +1,394 @@ +% !TEX program = pdflatex +% +% This is a test file demonstrating the keys3 experimental LaTeX3 +% package. This file illustrates the methods made available by keys3 +% for managing key-value input. It also acts as a check, as almost all +% of the keys3 methods are used (with known output) and because a number +% of errors are deliberately raised. + +\documentclass{article} +\usepackage{keys3,xparse} +\usepackage[parfill]{parskip} + +% The document commands for creating keys is very simple. A generic +% one is created to set any modules keys, and one specific to the module +% used here. +\ExplSyntaxOn + +\DeclareDocumentCommand{\SetModuleKeys}{m}{ + \keys_manage:n{ + module~name/.cd:, + #1} +} + +\DeclareDocumentCommand{\SetKeys}{m}{ + \keys_manage:n{#1} +} + +\ExplSyntaxOff + +\begin{document} + +% Each test starts with a short piece of text explaining the property +% being used. Under this, the expected output is given, followed +% if relevant by the text of any error messages expected. + +% Test one: Simply creating a key with one argument and then using it. +% Notice that the text length determines the limits of the argument: +% spaces at either end are ignored. Literal spaces between text are +% counted, as are those enclosed in braces. +% ---------------------------------------------------------------------- +% You said: `Hello World' +% You said: ` Hello World ' +% You said: `' +% ---------------------------------------------------------------------- +\SetModuleKeys{ + key/.code:n = {You said: `#1'\\}, + key = Hello World , + key = { Hello World }, + key +} + +% Test two: Creating a multiple-argument key. Here, the arguments +% given need to be at least as many as those required by the code! +% ---------------------------------------------------------------------- +% You said: `A', `B', `C', D'. +% You said: `AAA', `BBB', `CCC', ` DDD'. +% You said: `', `', `', `'. +% ---------------------------------------------------------------------- +\SetModuleKeys{ + key/.code:Nn = 4 {You said: `#1', `#2', `#3', `#4'.\\}, + key = ABCD, + key = {AAA}{BBB} {CCC} { DDD}, + key =, +} + +% Test three: The ability to change the key path is available with the +% .cd: property. The following moves from the key root to two separate +% paths, creating keys with the same names. +% ---------------------------------------------------------------------- +% A key in path one +% A key in path two +% A key in path two +% A key in path one +% ---------------------------------------------------------------------- +\SetKeys{ + /path one/.cd:, + key/.code:n = A key in path one\\, + /path two/.cd:, + key/.code:n = A key in path two\\, + /path one/key, + /path two/key, + key, + /path one/.cd:, + key +} + +% Test four: Variants of .code:n and .code:Nn exist which carry out a +% full expansion on code definition. First the :x variant is tested. +% ---------------------------------------------------------------------- +% Temp holds: ABC +% Temp hold: 123 +% ---------------------------------------------------------------------- +\newcommand*{\temp}{123} +\SetModuleKeys{ + key one/.code:n = Temp holds: \temp\\, + key two/.code:x = Temp holds: \temp, +} +\renewcommand*{\temp}{ABC} +\SetModuleKeys{ + key one, + key two +} +% Now the :Nx version +% ---------------------------------------------------------------------- +% Arguments: A, B. Temp holds: ABC +% Arguments: 1, 2. Temp hold: 123 +% ---------------------------------------------------------------------- +\renewcommand*{\temp}{123} +\SetModuleKeys{ + key one/.code:Nn = 2 {Arguments: #1, #2. Temp holds: \temp\\}, + key two/.code:Nx = 2 {Arguments: #1, #2. Temp holds: \temp}, +} + +\renewcommand*{\temp}{ABC} +\SetModuleKeys{ + key one = {A} {B}, + key two = {1} {2} +} + +% Test five: Values can be required and forbidden with the +% .value_required: and .value_forbidden: properties. +% ---------------------------------------------------------------------- +% All okay +% All okay +% ---------------------------------------------------------------------- +% The key `/module name/key' cannot taken a value: +% the given input `Not allowed' is being ignored. +% +% The key `/module name/key' requires a value +% and is being ignored. +% ---------------------------------------------------------------------- +\SetModuleKeys{ + key/.code:n = {All okay\\}, + key/.value_forbidden:, + key, + key = Not allowed, + key/.code:n = #1, + key/.value_required:, + key = {All okay}, + key +} + +% Test six: Keys can be given a default value, to be used if nothing is +% specified by the user. +% ---------------------------------------------------------------------- +% Default +% Real +% Default +% ---------------------------------------------------------------------- +\SetModuleKeys{ + key/.code:n = {#1\\}, + key/.default:n = Default, + key, + key = Real, + key +} + +% Test seven: Keys can be created to store data tl variable both +% locally and globally. +% ---------------------------------------------------------------------- +% Some content +% Outside +% Some content +% Some content +% ---------------------------------------------------------------------- +\renewcommand*{\temp}{Outside} +\SetModuleKeys{ + key one/.tl_set:N = \temp, +} +\begingroup +\SetModuleKeys{ + key = Some content +} +\temp\\ +\endgroup +\temp\\ +\SetModuleKeys{ + key/.tl_gset:N = \temp +} +\begingroup +\SetModuleKeys{ + key = Some content +} +\temp\\ +\endgroup +\temp\\ + +% Test eight: An expanded version of .tkp_set:N is available. +% ---------------------------------------------------------------------- +% Unexpanded +% Expanded +% ---------------------------------------------------------------------- +\renewcommand*{\temp}{Expanded} +\newcommand*{\tempa}{} +\newcommand*{\tempb}{} +\SetModuleKeys{ + key one/.tl_set:N = \tempa, + key two/.tl_set_x:N = \tempb, + key one = \temp, + key two = \temp, +} +\renewcommand*{\temp}{Unexpanded} +\tempa\\ +\tempb\\ + +% Test nine: Storage functions for int, skip and toks variables are also +% available. Both local and global setting is possible, although there +% are no "x" versions. +% ---------------------------------------------------------------------- +% 12345 +% 10.00002pt +% abc +% ---------------------------------------------------------------------- +\newcount\tempint +\newskip\tempskip +\newtoks\temptoks +\SetModuleKeys{ + key/.int_set:N = \tempint, + key = 12345, + key/.skip_set:N = \tempskip, + key = 1 em, + key/.toks_set:N = \temptoks, + key = abc +} +\the\tempint\\ +\the\tempskip\\ +\the\temptoks + +% Test ten: Variables can be identified only by the unique part of their +% name, provided that /keys/current_module:n has been set with the +% appropriate information. Both local and global names can be used in +% this way. +% ---------------------------------------------------------------------- +% Local +% Global +% ---------------------------------------------------------------------- +\ExplSyntaxOn +\tl_new:N \l_module_local_tl +\tl_new:N \g_module_global_tl +\ExplSyntaxOff +\SetModuleKeys{ + /keys/current_module:n = module, + key one/.tl_set:n = local, + key two/.tl_gset:n = global, + key one = Local, + key two = Global +} +\ExplSyntaxOn +\l_module_local_tl \\ +\g_module_global_tl +\ExplSyntaxOff + +% Test eleven: Boolean keys are created in the same way as other storage +% keys. However, the key will then only accept "true" and "false" as +% input. The key name can be given alone, resulting in the switch being +% set "true". +% ---------------------------------------------------------------------- +% Local switch true +% Global switch true +% ---------------------------------------------------------------------- +% Key `/module name/key one' takes the Boolean values +% `true' and `false' only. +% The given value `rubbish' is being ignored. +% ---------------------------------------------------------------------- +\ExplSyntaxOn +\bool_new:N \localbool +\bool_new:N \g_module_global_bool +\ExplSyntaxOff +\SetModuleKeys{ + /keys/current_module:n = module, + key one/.bool_set:N = \localbool, + key two/.bool_gset:n = global, + key one = true, + key two = false, + key two, + key one = rubbish +} +\ExplSyntaxOn +\bool_if:NTF \localbool { Local~switch~true } { Local~switch~false } \\ +\bool_if:NTF \g_module_global_bool + { Global~switch~true } { Global~switch~false } +\ExplSyntaxOff + +% Test twelve: The logic for Boolean keys can be reversed using the +% .bool_set_inverse:N and related properties. This can be used with +% in concert with .bool_set:N to create complementary keys. +% ---------------------------------------------------------------------- +% Hello World +% Hello User +% ---------------------------------------------------------------------- +\SetModuleKeys{ + /keys/current_module:n = module, + key one/.bool_set_inverse:N = \localbool, + key two/.bool_gset_inverse:n = global, + key one, + key two = true, +} +\ExplSyntaxOn +\bool_if:NTF \localbool { Local~switch~true } { Local~switch~false } \\ +\bool_if:NTF \g_module_global_bool + { Global~switch~true } { Global~switch~false } +\ExplSyntaxOff + +% Test thirteen: Choices can be created either from a list of options or +% one by one. Both are tested here by creating a list then adding to it +% with an extra key. Unknown choices lead to an error message. +% ---------------------------------------------------------------------- +% Choice `a' is number 1 +% Choice `b' is number 2 +% Choice `c' is number 3 +% An extra choice +% ---------------------------------------------------------------------- +% Choice `e' unknown for key `/module name/key/e': +% the key is being ignored. +% ---------------------------------------------------------------------- +\SetModuleKeys{ + key/.create_choices:nn = {a,b,c} + {Choice `\csname l_keys_current_choice_tl\endcsname' is number + \the\csname l_keys_current_choice_int\endcsname \\}, + key/d/.code:n = {An extra choice \\}, + key = a, + key = b, + key = c, + key = d, + key = e +} + +% Test fourteen: Keys can be used to set other keys. One or more +% arguments can be accepted when this happens, allowing complex key +% setting to be carried out easily. There are expanded versions of these +% properties, which work similarly. +% ---------------------------------------------------------------------- +% Hello Fred. +% How are you, Fred? +% Hello Fred. +% How are you, Ginger? +% ---------------------------------------------------------------------- +\SetModuleKeys{ + key one/.code:n = {Hello #1.\\}, + key two/.code:n = {How are you, #1?\\}, + key three/.use_keys:n = { key one = #1, key two = #1}, + key three = Fred, + key three/.use_keys:Nn = 2 { key one = #1, key two = #2}, + key three = {Fred} {Ginger} +} + +% Test fifteen: The .try:w and .retry:w properties attempt to set a key +% only if it exists. The .try:w property does this for every key it +% is given, whereas .retry: only works if the previous .try:w failed. +% ---------------------------------------------------------------------- +% Hello +% World +% Seen +% ---------------------------------------------------------------------- +\SetModuleKeys{ + key one/.code:n = {#1\\}, + key two/.code:n = {#1\\}, + key one/.try:n = Hello, + key ten/.try:n = Rubbish, + key two/.try:n = World, + key two/.retry:n = Not seen, + key ten/.try:n = Rubbish, + key two/.retry:n = Seen, +} + +% Test sixteen: Two programmers tools, .show_code: and .show_key:, do +% pretty much what might be expected. .show_key: is mainly useful for +% internal keys. +% ---------------------------------------------------------------------- +% a or b +% ---------------------------------------------------------------------- +% > \keys-root/module name/key one/._cmd:w=\long macro: +% #1#2->#1 or #2. +% +% > \keys-root/module name/key one/._num_args_tl=macro: +% ->2. +% ---------------------------------------------------------------------- +\SetModuleKeys{ + key one/.code:Nn = 2 {#1 or #2}, + key one = ab, + key one/.show_code:, + key one/._num_args_tl/.show_key:, +} + +% Test seventeen: A completely unknown key should cause an error. +% ---------------------------------------------------------------------- +% The key `/module name/unknown key' is unknown and is being ignored +% ---------------------------------------------------------------------- +\SetModuleKeys{ + unknown key = some value +} + +\end{document} + diff --git a/Master/texmf-dist/doc/latex/keys3/keys3.pdf b/Master/texmf-dist/doc/latex/keys3/keys3.pdf Binary files differnew file mode 100644 index 00000000000..3d26fd7fdfe --- /dev/null +++ b/Master/texmf-dist/doc/latex/keys3/keys3.pdf diff --git a/Master/texmf-dist/doc/latex/keys3/keys3opts2.pdf b/Master/texmf-dist/doc/latex/keys3/keys3opts2.pdf Binary files differnew file mode 100644 index 00000000000..cdc4783125a --- /dev/null +++ b/Master/texmf-dist/doc/latex/keys3/keys3opts2.pdf diff --git a/Master/texmf-dist/source/latex/keys3/keys3.dtx b/Master/texmf-dist/source/latex/keys3/keys3.dtx new file mode 100644 index 00000000000..6932050bb8c --- /dev/null +++ b/Master/texmf-dist/source/latex/keys3/keys3.dtx @@ -0,0 +1,2267 @@ +% \iffalse meta-comment +% !TEX program = pdflatex +% !TEX encoding = ISO-8859-1 +%<*internal> +\iffalse +%</internal> +%<*readme> +--------------------------------------------------------------- +The keys3 package --- Key management for LaTeX3 +Maintained by Joseph Wright +E-mail: joseph.wright@morningstar2.co.uk +Released under the LaTeX Project Public License v1.3c or later +See http://www.latex-project.org/lppl.txt +--------------------------------------------------------------- + +The keys3 package is an experimental implementation of key +management for LaTeX3. The entire package is written in +expl3 code rather than in traditional TeX/LaTeX. The key +module used by keys3 is based on that introduced by the +pgfkeys package from the pgf/TiKZ bundle. Keys are thus +addressed in a path-like manner, and are controlled by key +properties: + +/module/key/.code:n = <code>, +/module/key/.value_required:, +/module/key = <value> + +The keys3 package is intended as a method for testing how key +management might be implemented in LaTeX3. Both the methods +used inside the package and the interface provided are intended +to be discussed. Feedback is welcomed either by e-mail +(joseph.wright@morningstar2.co.uk) or at the package website +(http://keys3.berlios.de). + +The experimental nature of keys3 and the underlying expl3 +system means that it should not be used in production +documents. However, programmers testing expl3, or keen to work +on improved key management systems, are encouraged to try the +package and provide feedback. + +keys3 is *not* an official LaTeX3 team package. Whether any of +the ideas explored here will be taken up by the team is +therefore unknown. However, the keys3 package should provide +ideas on what needs to be available for key management and how +it can be implemented. +%</readme> +%<*internal> +\fi +\def\nameofplainTeX{plain} +\ifx\fmtname\nameofplainTeX\else + \expandafter\begingroup +\fi +%</internal> +%<*install> +\input docstrip.tex +\keepsilent +\askforoverwritefalse +\preamble +--------------------------------------------------------------- +The keys3 package --- Key management for LaTeX3 +Maintained by Joseph Wright +E-mail: joseph.wright@morningstar2.co.uk +Released under the LaTeX Project Public License v1.3c or later +See http://www.latex-project.org/lppl.txt +--------------------------------------------------------------- + +EXPERIMENTAL CODE + +Do not distribute this file without also distributing the +source files specified above. + +Do not distribute a modified version of this file. + +\endpreamble +\postamble + +Copyright (C) 2008-2009 by + Joseph Wright <joseph.wright@morningstar2.co.uk> + +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 work is "maintained" (as per LPPL maintenance status) by + Joseph Wright. + +This work consists of the file keys3.dtx + and the derived files keys3.pdf, + keys3.sty and + keys3.ins. + +\endpostamble +\usedir{tex/latex/keys3} +\generate{ + \file{\jobname.sty}{\from{\jobname.dtx}{package}} +} +%</install> +%<install>\endbatchfile +%<*internal> +\usedir{source/latex/keys3} +\generate{ + \file{\jobname.ins}{\from{\jobname.dtx}{install}} +} +\nopreamble\nopostamble +\usedir{doc/latex/keys3} +\generate{ + \file{README.txt}{\from{\jobname.dtx}{readme}} +} +\ifx\fmtname\nameofplainTeX + \expandafter\endbatchfile +\else + \expandafter\endgroup +\fi +%</internal> +%<*driver|package> +\RequirePackage{expl3} +\GetIdInfo$Id: keys3.dtx 101 2009-06-10 12:16:20Z josephwright $ + {Key management for LaTeX3} +%</driver|package> +%\fi +%\iffalse +%<*driver> +%\fi +\ProvidesFile{\filename.\filenameext} + [\filedate\space v\fileversion\space\filedescription] +%\iffalse +\documentclass[full]{l3doc} +\begin{document} + \DocInput{\filename.\filenameext} +\end{document} +%</driver> +% \fi +% +% \title{The \pkg{keys3} package^^A +% \thanks{This file has version number \fileversion, last +% revised \filedate.}\\ +% Key management for \LaTeX3} +% \author{Joseph Wright^^A +% \thanks{E-mail: joseph.wright@morningstar2.co.uk}} +% \date{\filedate} +% +% \maketitle +% +% \begin{documentation} +% +%\section{Key management} +% +% The key--value method is a popular system for creating large numbers +% of settings for controlling macro or package behaviour. For the +% user, the system normally results in input of the form +%\begin{verbatim} +% \PackageControlMacro{ +% key = value, +% key two = value two +% } +%\end{verbatim} +% or +%\begin{verbatim} +% \PackageMacro[ +% key = value, +% key two = value two +% ]{argument}. +%\end{verbatim} +% For the programmer, the original \pkg{keyval} package gives only +% the most basic interface for this work. All key macros have to be +% created one at a time, and as a result the \pkg{kvoptions} and +% \pkg{xkeyval} packages have been written to extend the ease of +% creating keys. However, the underlying model is rather inflexible. +% +% As an alternative, \pkg{pgfkeys} from the \pkg{pgf}/Ti\emph{k}z +% bundle uses a ``file-like'' model for keys. In this model, each key +% has one or more functions attached to define its action. In +% \pkg{pgfkeys} terminology, these are key \emph{handlers}. Keys can +% be created and used using a unified interface: +%\begin{verbatim} +% \pgfkeys{ +% /path/key/.handler = code, +% /path/key = value +% } +%\end{verbatim} +% +% The \pkg{keys3} package is aimed at creating a high-level +% programmers interface for key--value controls in \LaTeX3. Key +% creation and control follows the \pkg{pgfkeys} closely, although +% changes have been made to adhere to the new coding ideas of \LaTeX3, +% and new functions have been added. The \pkg{keys3} package is +% \emph{not} a simple translation of \pkg{pgfkeys} to the new syntax. +% In package internals have been written from the ground up, to better +% enforce variable typing and to act in a know manner under failing +% circumstances. +% +% In the \pkg{keys3} model, each key belongs to a module, +% which may have one or more subdivisions. Each key then has +% one or more properties which define how the key acts. The idea +% of a single function for all key control is retained: +%\begin{verbatim} +% \keys_manage:n{ +% /module/key/.property = code, +% /module/sub/key/.property = more code, +% /module/key = value +% } +%\end{verbatim} +% The combination of all \m{module} parts up to the \m{key} is referred +% to as the \emph{path} of the key. +% +% Keys are created by assigning one or more properties to the key, +% most commonly a piece of code to execute when the key is used (this +% is the \texttt{.code:n} property). +%\begin{verbatim} +% \keys_manage:n{ +% /module/key/.code:n = <code> +% } +%\end{verbatim} +% Keys are then used in the normal way, by assigning a value to the +% key. +%\begin{verbatim} +% \keys_manage:n{ +% /module/key = <value> +% } +%\end{verbatim} +% Here, \meta{value} is passed to the \meta{code} defined |#1|. The +% \meta{code} can then process it in whatever way is appropriate. +% +% At a document level, it is likely that \cs{keys_manage:n} would be +% wrapped up into a user macro or optional argument. For \LaTeXe, a +% generic set up macro might be created with: +%\begin{verbatim} +% \newcommand*\SomePackageSetup[1]{% +% \@nameuse{keys_manage:n}{% +% /package name/.cd:, +% #1 +% }% +% } +%\end{verbatim} +% or to use key--value input as the optional argument for a macro: +%\begin{verbatim} +% \newcommand*\SomePackageMacro[2][]{% +% \begingroup +% \@nameuse{keys_manage:n}{ +% /package name/.cd:, +% #1 +% }% +% % Main code for \SomePackageMacro +% \endgroup +% } +%\end{verbatim} +% The same concepts using \pkg{xparse} for \LaTeX3 use: +%\begin{verbatim} +% \DeclareDocumentCommand \SomePackageSetup { m } { +% \keys_manage:n { +% /package name/.cd:, +% #1 +% } +% } +% \DeclareDocumentCommand \SomePackageMacro { o m } { +% \group_begin: +% \keys_manage:n { +% /package name/.cd:, +% #1 +% } +% % Main code for \SomePackageMacro +% \group_end: +% } +%\end{verbatim} +% +%\subsection{Creating, retrieving and setting keys} +% +% The main interface for key management is the the \cs{keys_manage:n} +% macro. This can be used to create, retrieve and set keys, and is +% therefore the preferred interface for the package. +% +% \begin{function}{ +% \keys_manage:n| +% \keys_manage_quick:n +% } +% \begin{syntax} +% "\keys_manage:n" <keyval list> +% \end{syntax} +% The main key management function, which parses over the <keyval +% list> and processes each key. The standard version removes leading +% and trailing spaces and checks catcodes for ungrouped ``|,|'' and +% ``|=|'' tokens. The |_quick| version omits these tests for speed, +% and is therefore more suited to creating keys inside code blocks. +% \end{function} +% +% \begin{function}{ +% \keys_manage:nn| +% \keys_manage_quick:nn| +% } +% \begin{syntax} +% "\keys_manage:nn" <path> <keyval list> +% \end{syntax} +% Versions of the above which include a <path> as an argument. These +% are faster versions of the |:n| macros when setting lots of keys +% separately and with known paths. +% \end{function} +% +% Setting up and altering keys is carried out using one or more +% properties (in \pkg{pgfkeys}, these are called handlers). In all +% cases, \m{key} may be a full-qualified key with a path, or a partial +% key to which the default path will be added. Notice that when a +% single argument is required, the braces around the argument may be +% omitted without any error arising. +% +%\subsubsection{Storing values} +% +% A common use of key--value input is to store the values given in a +% variable for later use. \pkg{keys3} provides pre-defined +% properties for storing in integer, skip, token list variables and +% token registers. The method is similar in all cases: +%\begin{verbatim} +% \keys_manage:n{ +% /module/key~one/.int_set:N = \l_mod_data_int, +% /module/key~two/.skip_set:N = \l_mod_data_skip, +% /module/key~three/.tl_set:N = \l_mod_data_tl, +% /module/key~four/.toks_set:N = \l_mod_data_toks +% } +%\end{verbatim} +% These assignments are local: in each case, a global variant is +% available, with \texttt{set} replaced by \texttt{gset}. For example, +% \texttt{.tl_get:N} globally stores values in a token list variable. +% +% When using keys to store a value, it is often convenient to give only +% the unique part of the variable name. This is particularly true when +% creating a large number of related storage areas. To achieve this, +% \pkg{keys3} requires that the module prefix to be used is defined +% first. The special key \texttt{/keys/current_module:n} can be set with +% the name of the current module. +%\begin{verbatim} +% \keys_manage:n{ +% /keys/current_module:n = module, +% /module/key/.tl_set:n = my_data, +% } +%\end{verbatim} +% This will use a variable called \cs{l_module_my_data_tl} to store the +% input. Thus the preceding code achieves the same effect as +%\begin{verbatim} +% \keys_manage:n{ +% /module/key/.tl_set:N = \l_module_my_data_tl +% } +%\end{verbatim} +% The same method applies to int, skip and toks variables. The +% appropriate prefix (\cs{l_} or \cs{g_}) and suffix (|_int|, |_skip|, +% |_tl| or |_toks|) is always added. +% +%\subsubsection{Multiple choice keys} +% +% Multiple choice keys are created in \pkg{keys3} using the +% \texttt{.expects_choice:} property. Each choice is then a sub-key of +% the choice key. +%\begin{verbatim} +% \keys_manage:n{ +% /module/key/.expects_choice:, +% /module/key/choice~a/.code:n = Some code, +% /module/key/choice~b/.code:n = Some other code, +% } +%\end{verbatim} +% In this way, choices which execute arbitrary code can be created. +% Notice that the \m{code} should \emph{not} include a parameter (|#1|). +% +% Often it is desirable to create a family of similar choices, which +% only require either the text of the choice, or the position of the +% choice in a list, to be used. To create this type of simple choice, +% \pkg{keys3} provides the \texttt{.create_choices:nn} property. This +% applies the same code to a list of choice text. Inside the code, +% the name of the choice given is available as +% \cs{l_keys_current_choice_tl}. The position of the choice in the +% lists is also available, as \cs{l_keys_current_choice_int}. +%\begin{verbatim} +% \keys_manage:n { +% /module/key/.create_choices:nn = {choice~a, choice~b, choice~c} { +% You~gave~choice~``\l_keys_current_choice_tl'',~which~is~in~ +% position~\l_keys_current_choice_int\~in~the~list. +% } +% } +%\end{verbatim} +% +%\subsection{Properties} +% +% \begin{function}{ +% .bool_set:N| +% .bool_gset:N| +% } +% \begin{syntax} +% <key>/.bool_set:N = <bool> +% \end{syntax} +% Defines <key> to set <bool> to <value> (which must be either +% \texttt{true} or \texttt{false}). +% \end{function} +% +% \begin{function}{ +% .bool_set:n| +% .bool_gset:n| +% } +% \begin{syntax} +% <key>/.bool_set:n = <name> +% \end{syntax} +% Defines <key> to set switch with unique <name> to <value> (which +% must be either \texttt{true} or \texttt{false}). The switch +% name will be constructed using the current <module> (if any), +% prefixed by |\l_| and ending with |_int|. +% \end{function} +% +% \begin{function}{ +% .bool_set_inverse:N| +% .bool_gset_inverse:N| +% } +% \begin{syntax} +% <key>/.bool_set_inverse:N = <bool> +% \end{syntax} +% Defines <key> to set <bool> to <value> (which must be either +% \texttt{true} or \texttt{false}), with reversed logic. +% \end{function} +% +% \begin{function}{ +% .bool_set_inverse:n| +% .bool_gset_inverse:n| +% } +% \begin{syntax} +% <key>/.bool_set_inverse:n = <name> +% \end{syntax} +% Defines <key> to set switch with unique <name> to <value> (which +% must be either \texttt{true} or \texttt{false}), with reversed logic. +% The switch name will be constructed using the current <module> (if +% any), prefixed by |\l_| and ending with |_int|. +% \end{function} +% +% \begin{function}{.cd:} +% \begin{syntax} +% <key>/.cd: +% \end{syntax} +% Changes path to <key>. +% \end{function} +% +% \begin{function}{ +% .code:n| +% .code:x +% } +% \begin{syntax} +% <key>/.code:n = <code> +% \end{syntax} +% Stores the <code> for execution when <key> is called. The <code> can +% include one parameter (|#1|). +% \end{function} +% +% \begin{function}{ +% .code:Nn| +% .code:Nx +% } +% \begin{syntax} +% <key>/.code:Nn = <number> <code> +% \end{syntax} +% Stores the <code> for execution when <key> is called. The <code> can +% include <number> parameters, which can be in the range 0--9. +% \end{function} +% +% \begin{function}{ +% .create_choices:nn| +% .create_choices:nx| +% } +% \begin{syntax} +% <key>/.create_choices:nn = <list> <code> +% \end{syntax} +% Creates a sub-key of <key> for each <choice> in the comma-separated +% <list>. Each <choice> will have <code> associated with it. The +% current choice text is available as \cs{l_keys_current_choice_tl}, +% and its position in the <list> as \cs{l_keys_current_choice_int}. +% \end{function} +% +% \begin{function}{.default:n} +% \begin{syntax} +% <key>/.default:n = <content> +% \end{syntax} +% Creates a default value for <key>, which is used if no value is +% given. The <content> is stored as a token list variable, and so +% must be compatible with this variable type. +% \end{function} +% +% \begin{function}{.expects_choice:} +% \begin{syntax} +% <key>/.expects_choice: +% \end{syntax} +% Indicates that the <value> given for <key> should be a sub-key of +% <key>. In this way, <key> accepts one of a limited range of choices. +% \end{function} +% +% \begin{function}{ +% .int_set:N| +% .int_gset:N| +% } +% \begin{syntax} +% <key>/.int_set:N = <int> +% \end{syntax} +% Defines <key> to store <value> in the <int> named. +% \end{function} +% +% \begin{function}{ +% .int_set:n| +% .int_gset:n| +% } +% \begin{syntax} +% <key>/.int_set:n = <name> +% \end{syntax} +% Defines <key> to store <value> in a int with unique name <name>. The +% int name will be constructed using the current <module> (if any), +% prefixed by |\l_| and ending with |_int|. +% \end{function} +% +% \begin{function}{.retry:n} +% \begin{syntax} +% <key>/.retry:n = <data> +% \end{syntax} +% Executes <key> if it exists and if the previous \texttt{.try:n} +% failed. The <data> is passed to <key>, if successful. +% \end{function} +% +% \begin{function}{ +% .show_code:| +% .show_key:| +% } +% \begin{syntax} +% <key>/.show_code: +% <key>/.show_key: +% \end{syntax} +% Shows the function for the current key or the code associated with +% the current key. +% \end{function} +% +% \begin{function}{ +% .skip_set:N| +% .skip_gset:N| +% } +% \begin{syntax} +% <key>/.skip_set:N = <skip> +% \end{syntax} +% Defines <key> to store <value> in the <skip> named. +% \end{function} +% +% \begin{function}{ +% .skip_set:n| +% .skip_gset:n| +% } +% \begin{syntax} +% <key>/.skip_set:n = <name> +% \end{syntax} +% Defines <key> to store <value> in a skip with unique name <name>. The +% skip name will be constructed using the current <module> (if any), +% prefixed by |\l_| and ending with |_skip|. +% \end{function} +% +% \begin{function}{ +% .tl_set:N| +% .tl_set_x:N| +% .tl_gset:N| +% .tl_gset_x:N| +% } +% \begin{syntax} +% <key>/.tl_set:N = <tl> +% \end{syntax} +% Defines <key> to store <value> in the <tl> named. The \texttt{x} +% versions use \cs{tl_(g)set:Nx} for this process, the standard +% version \cs{tl_(g)set:Nn}. +% \end{function} +% +% \begin{function}{ +% .tl_set:n| +% .tl_set_x:n| +% .tl_gset:n| +% .tl_gset_x:n| +% } +% \begin{syntax} +% <key>/.tl_set:n = <name> +% \end{syntax} +% Defines <key> to store <value> in a tl with unique name <name>. The +% tl name will be constructed using the current <module> (if any), +% prefixed by |\l_| and ending with |_tl|. +% \end{function} +% +% \begin{function}{ +% .toks_set:N| +% .toks_gset:N| +% } +% \begin{syntax} +% <key>/.toks_set:N = <toks> +% \end{syntax} +% Defines <key> to store <value> in the <toks> named. +% \end{function} +% +% \begin{function}{ +% .toks_set:n| +% .toks_gset:n| +% } +% \begin{syntax} +% <key>/.toks_set:n = <name> +% \end{syntax} +% Defines <key> to store <value> in a toks with unique name <name>. The +% rest of the toks name will be constructed using the current <module> +% (if any), prefixes by |\l_| and ending with |_toks|. +% \end{function} +% +% \begin{function}{.try:n} +% \begin{syntax} +% <key>/.try:n = <data> +% \end{syntax} +% Executes <key> if defined, and does nothing otherwise. The <data> is +% passed to <key>, if successful. +% \end{function} +% +% \begin{function}{ +% .use_keys:n| +% .use_keys:x| +% } +% \begin{syntax} +% <key>/.use_keys:n = <keyval list> +% \end{syntax} +% Calling <key> applies the <keyval list> as a block. Thus one <key> +% can make many related settings. As usual, |#1| is available in the +% <keyval list> as <key> will take one argument. +% \end{function} +% +% \begin{function}{ +% .use_keys:Nn| +% .use_keys:Nx| +% } +% \begin{syntax} +% <key>/.use_keys:Nn = <number> <keyval list> +% \end{syntax} +% Calling <key> applies the <keyval list> as a block. Thus one <key> +% can make many related settings. The <key> will take <number> of +% arguments, which can be used inside the <keyval list>. +% \end{function} +% +% \begin{function}{ +% .value_forbidden:| +% .value_required:| +% } +% \begin{syntax} +% <key>/.value_forbidden: +% \end{syntax} +% Flags for forbidding and requiring a <value> for <key>. +% \end{function} +% +%\subsection{Variables and constants} +% +% \begin{variable}{ +% \c_keys_0_empty_tl| +% \c_keys_1_empty_tl| +% \c_keys_2_empty_tl| +% \c_keys_3_empty_tl| +% \c_keys_4_empty_tl| +% \c_keys_5_empty_tl| +% \c_keys_6_empty_tl| +% \c_keys_7_empty_tl| +% \c_keys_8_empty_tl| +% \c_keys_9_empty_tl| +% } +% A set of token list variables containing empty groups. +% \end{variable} +% +% \begin{variable}{\c_keys_cs_prefix_tl} +% The prefix added to the fully-qualified key when saving them. +% \end{variable} +% +% \begin{variable}{ +% \c_keys_errors_path_tl| +% \c_keys_properties_path_tl| +% \c_keys_utilities_path_tl| +% } +% Paths for properties used by \pkg{l3keys} itself. +% \end{variable} +% +% \begin{variable}{\c_keys_root_tl} +% The root path for keys. +% \end{variable} +% +% \begin{variable}{\l_keys_choice_code_tl} +% The code to execute for each multiple choice when created \emph{en +% masse}. +% \end{variable} +% +% \begin{variable}{ +% \l_keys_current_choice_tl| +% \l_keys_current_choice_int| +% } +% Information on multiple choices. +% \end{variable} +% +% \begin{variable}{ +% \l_keys_current_key_full_tl| +% \l_keys_current_key_name_tl| +% } +% The current key name is stored both with and without a path. +% \end{variable} +% +% \begin{variable}{\l_keys_current_module_tl} +% Current module name used when creating csnames. +% \end{variable} +% +% \begin{variable}{ +% \l_keys_current_path_tl| +% \l_keys_default_path_tl| +% \l_keys_choice_path_tl| +% } +% Various key paths need to be stored. +% \end{variable} +% +% \begin{variable}{\l_keys_current_value_toks} +% The value given for the current key, stored as a token register. +% \end{variable} +% +% \begin{variable}{\l_keys_no_value_bool} +% A marker for ``no value'' as key input. +% \end{variable} +% +% \begin{variable}{\l_keys_success_bool} +% A marker used when trying keys without raising errors. +% \end{variable} +% +% \begin{variable}{\l_keys_tmpa_tl} +% A scratch variable. +% \end{variable} +% +%\subsection{Internal functions} +% +% Notice that everything should be done using the keys system. Only +% \cs{keys_manage:n} and so on are intended for external use. In all +% cases, \m{key} is a fully-qualified key name. Functions created will +% be prefixed with \cs{c_keys_cs_prefix_tl}. +% +% \begin{function}{\keys_bool_new:n} +% \begin{syntax} +% "\keys_bool_new:n" <key> +% \end{syntax} +% Creates a switch <key>, which will be set to \texttt{true}. +% \end{function} +% +% \begin{function}{ +% \keys_bool_set:nN| +% \keys_bool_set:nnn| +% } +% \begin{syntax} +% "\keys_bool_set:nN" <function> <boolean> +% "\keys_bool_set:nnn" <function> <prefix> <name> +% \end{syntax} +% Uses <function> (either \texttt{set} or \texttt{gset}) to use +% <value> in setting <boolean>. If a <name> is given, it is used to +% construct a csname for the switch including the current <module>. +% The <prefix> should be |l_| or |g_|. +% \end{function} +% +% \begin{function}{ +% \keys_bool_set_inverse:n| +% \keys_bool_set_inverse:nN| +% \keys_bool_set_inverse:nnn| +% } +% \begin{syntax} +% "\keys_bool_set:n" <switch> +% "\keys_bool_set:nN" <function> <boolean> +% "\keys_bool_set:nnn" <function> <prefix> <name> +% \end{syntax} +% Uses <function> (either \texttt{set} or \texttt{gset}) to use +% <value> in setting <boolean>. If a <name> is given, it is used to +% construct a csname for the switch including the current <module>. +% The <prefix> should be |l_| or |g_|. The logic of the setting is +% reversed compared to the \cs{keys_bool_set:} functions. +% \end{function} +% +% \begin{function}{ +% \keys_check_exists:NN| +% \keys_check_exists:cN +%} +% \begin{syntax} +% "\keys_check_exists:NN" <var> <new cmd> +% \end{syntax} +% Checks that <var> exists and if not used <new cmd> to create it. +% \end{function} +% +% \begin{function}{\keys_choice_create:n} +% \begin{syntax} +% "\keys_choice_create:n" <choice> +% \end{syntax} +% Creates <choice> as a sub-key of <key>. +% \end{function} +% +% \begin{function}{\keys_choices_create:Nnn} +% \begin{syntax} +% "\keys_choices_create:Nnn" <expansion> <list> <code> +% \end{syntax} +% Takes a comma separated <list> and makes a <choice> as a sub-key of +% the current <key> for each. The <choice> will execute <code>, which +% is processed according to <expansion> (either \texttt{n} or +% \texttt{x}). The <code> has access to \cs{l_keys_current_choice_tl} +% and \cs{l_keys_current_choice_int}, which indicate the choice given. +% \end{function} +% +% +% \begin{function}{\keys_clear_properties:n} +% \begin{syntax} +% "\keys_clear_properties:n" <key> +% \end{syntax} +% Clears the internal properties of <key>. +% \end{function} +% +% \begin{function}{\keys_default_add:} +% \begin{syntax} +% "\keys_default_add:" +% \end{syntax} +% If no value was given for the current key, and a default value is +% available, copies the default into \cs{l_keys_current_value_toks}. +% \end{function} +% +% \begin{function}{\keys_msg_new:nn} +% \begin{syntax} +% "\keys_msg_new:nn" <name> <text> +% \end{syntax} +% Creates a new message with <name> which produces <text>. +% \end{function} +% +% \begin{function}{ +% \keys_error:nn| +% \keys_error:n| +% } +% \begin{syntax} +% "\keys_error:nn" <name> <arg> +% "\keys_error:n" <name> +% \end{syntax} +% Issues error <name>, with or without <argument>. +% \end{function} +% +% \begin{function}{ +% \keys_find_code_full:| +% \keys_find_code_name: +% } +% \begin{syntax} +% "\keys_find_code_full:" +% "\keys_find_code_name:" +% \end{syntax} +% Find code to execute for the current fully qualified key +% (\texttt{full}) or key name only (\texttt{name}). +% \end{function} +% +% \begin{function}{\keys_if_cmd_exist:n / (TF)} +% \begin{syntax} +% "\keys_if_cmd_exist:nTF" <key> <true code> +% ~~~~<false code> +% \end{syntax} +% Checks for the existence of a |._cmd:w| function for <key>. +% \end{function} +% +% \begin{function}{\keys_if_exist:n / (TF)} +% \begin{syntax} +% "\keys_if_exist:nTF" <key> <true code> +% ~~~~<false code> +% \end{syntax} +% Checks for the existence of a <key>. +% \end{function} +% +% \begin{function}{\keys_if_value:n / (TF)} +% \begin{syntax} +% "\keys_if_value:nTF" <property> <true code> <false code> +% \end{syntax} +% Checks for the <property> switch of a <key> (typically +% \texttt{required} or \texttt{forbidden}). +% \end{function} +% +% \begin{function}{\keys_manage_internal:n} +% \begin{syntax} +% "\keys_manage_internal:n" <keyval list> +% \end{syntax} +% An internal ``recycling'' version of \cs{keys_manage_quick:n}, which +% should not be called from outside. +% \end{function} +% +% \begin{function}{ +% \keys_no_value_elt:n| +% \keys_value_elt:nn +% } +% \begin{syntax} +% "\keys_no_value_elt:n" <elt> +% "\keys_value_elt:nn" <elt> <value> +% \end{syntax} +% Functions used by \pkg{l3keyval} for each <elt> of the <keyval +% list> being processed. +% \end{function} +% +% \begin{function}{\keys_parse:n} +% \begin{syntax} +% "\keys_parse:n" <keyval list> +% \end{syntax} +% Functions which actually parses <keyval list>. +% \end{function} +% +% \begin{function}{\keys_parse_list:n} +% \begin{syntax} +% "\keys_parse_list:n" <keyval list> +% \end{syntax} +% Set up macro for \cs{keys_parse:n}. +% \end{function} +% +% \begin{function}{ +% \keys_path_add:N| +% \keys_path_add:w +% } +% \begin{syntax} +% "\keys_path_add:N" <tl> +% "\keys_path_add:w" <tlist> "\q_stop" +% \end{syntax} +% Adds a full path to key name stored in <tl> or given as <tlist>. +% \end{function} +% +% \begin{function}{\keys_process_elt:nn} +% \begin{syntax} +% "\keys_process_elt:nn" <elt> <value> +% \end{syntax} +% Lead-off processor for converting <elt> into a fully-qualified +% <key> and checking validity of <value>. +% \end{function} +% +% \begin{function}{ +% \keys_separate_path:| +% \keys_separate_path:w +% } +% \begin{syntax} +% "\keys_separate_path:" +% "\keys_separate_path:w" / <path 1> / <path 2> "\q_stop" +% \end{syntax} +% Separates key into <path> and <key name>. +% \end{function} +% +% \begin{function}{ +% \keys_set:NN| +% \keys_set:Nnn| +% } +% \begin{syntax} +% "\keys_set:NN" <function> <variable> +% "\keys_set:Nnn" <function> <prefix> <name> +% \end{syntax} +% Uses <function> to store <value> in <variable>. If a <name> is +% given, it is used to construct a csname for the variable including +% the current <module>. The <prefix> should be |l_| or |g_|. +% \end{function} +% +% \begin{function}{ +% \keys_set_cmd:nn| +% \keys_set_cmd:nx| +% \keys_set_cmd:nNn| +% \keys_set_cmd:nNx| +% } +% \begin{syntax} +% "\keys_set_cmd:nn" <key> <code> +% "\keys_set_cmd:nNn" <key> <number> <code> +% \end{syntax} +% Creates a |._cmd:w| function for <key>, with definition <code>. The +% \texttt{N} variant can include <number> parameters. +% \end{function} +% +% \begin{function}{ +% \keys_store:nn| +% \keys_store:nx +% } +% \begin{syntax} +% "\keys_store:nn" <key> <data> +% \end{syntax} +% Stores <data> in <key> function. +% \end{function} +% +% \begin{function}{\keys_toks_set:Nn} +% \begin{syntax} +% "\keys_toks_set:Nn" <toks> <key> +% \end{syntax} +% Sets <toks> equal to the content of <key> +% \end{function} +% +% \begin{function}{\keys_try:} +% \begin{syntax} +% "\keys_try:" +% \end{syntax} +% Attempt to execute a key, with no error if the key is unknown. +% \end{function} +% +% \begin{function}{\keys_undefine:n} +% \begin{syntax} +% "\keys_undefine:n" <key> +% \end{syntax} +% Delete definition of <key>. +% \end{function} +% +% \begin{function}{\keys_use:n} +% \begin{syntax} +% "\keys_use:n" <key> +% \end{syntax} +% Use definition of <key>. +% \end{function} +% +% \begin{function}{ +% \keys_use_cmd:n| +% \keys_use_cmd:nn +% } +% \begin{syntax} +% "\keys_use_cmd:n" <key> +% "\keys_use_cmd:nn" <key> <arg> +% \end{syntax} +% Uses the |._cmd:w| function for <key>, passing <arg> if needed. +% \end{function} +% +%\subsubsection{Internal properties} +% +% The internal key properties should not be accessed directly. +% +% \begin{function}{._cmd:w} +% \begin{syntax} +% \end{syntax} +% The function which is executed for a key with \texttt{.code}. +% \end{function} +% +% \begin{function}{._default_tl} +% \begin{syntax} +% \end{syntax} +% Holds the default value for a key. +% \end{function} +% +% \begin{function}{._forbidden_bool} +% \begin{syntax} +% \end{syntax} +% Indicates that a value cannot be given for <key>. +% \end{function} +% +% \begin{function}{._num_args_tl} +% \begin{syntax} +% \end{syntax} +% For functions defined with \texttt{.code:Nn} and \texttt{.code:Nx}, +% contains the number of arguments the associated |._cmd:w| function +% takes. +% \end{function} +% +% \begin{function}{._required_bool} +% \begin{syntax} +% \end{syntax} +% Indicates that <key> must have a value provided. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +%\subsection{Implementation} +% +% The usual preliminaries. +% \begin{macrocode} +%<*package> +\ProvidesExplPackage + {\filename}{\filedate}{\fileversion}{\filedescription} +% \end{macrocode} +% +%\subsubsection{Variables and contrasts} +% +%\begin{macro}{\c_keys_0_empty_tl} +%\begin{macro}{\c_keys_1_empty_tl} +%\begin{macro}{\c_keys_2_empty_tl} +%\begin{macro}{\c_keys_3_empty_tl} +%\begin{macro}{\c_keys_4_empty_tl} +%\begin{macro}{\c_keys_5_empty_tl} +%\begin{macro}{\c_keys_6_empty_tl} +%\begin{macro}{\c_keys_7_empty_tl} +%\begin{macro}{\c_keys_8_empty_tl} +%\begin{macro}{\c_keys_9_empty_tl} +% A set of empty arguments. +% \begin{macrocode} +\tl_new:cn { c_keys_0_empty_tl } {} +\tl_new:cn { c_keys_1_empty_tl } { {} } +\tl_new:cn { c_keys_2_empty_tl } { {} {} } +\tl_new:cn { c_keys_3_empty_tl } { {} {} {} } +\tl_new:cn { c_keys_4_empty_tl } { {} {} {} {} } +\tl_new:cn { c_keys_5_empty_tl } { {} {} {} {} {} } +\tl_new:cn { c_keys_6_empty_tl } { {} {} {} {} {} {} } +\tl_new:cn { c_keys_7_empty_tl } { {} {} {} {} {} {} {} } +\tl_new:cn { c_keys_8_empty_tl } { {} {} {} {} {} {} {} {} } +\tl_new:cn { c_keys_9_empty_tl } { {} {} {} {} {} {} {} {} {} } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\c_keys_cs_prefix_tl} +% First, the small number of constants needed are created. A prefix is +% used to keep all of the actual key macros in one place. +% \begin{macrocode} +\tl_new:Nn \c_keys_cs_prefix_tl { keys-root } +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\c_keys_errors_path_tl} +%\begin{macro}{\c_keys_properties_path_tl} +%\begin{macro}{\c_keys_utilities_path_tl} +% The locations of all of the keys used by \pkg{keys3} itself. +% \begin{macrocode} +\tl_new:Nn \c_keys_errors_path_tl { /keys/errors } +\tl_new:Nn \c_keys_properties_path_tl { /keys/properties } +\tl_new:Nn \c_keys_utilities_path_tl { /keys } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\c_keys_root_tl} +% The key root should have a clear name; like all of the key macros, +% this does not include the prefix. +% \begin{macrocode} +\tl_new:Nn \c_keys_root_tl { / } +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_keys_choice_code_tl} +% When making choices, the code for each key has to be stored. +% \begin{macrocode} +\tl_new:N \l_keys_choice_code_tl +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_keys_current_choice_tl} +%\begin{macro}{\l_keys_current_choice_int} +% Multiple choices need some storage. +% \begin{macrocode} +\tl_new:N \l_keys_current_choice_tl +\int_new:N \l_keys_current_choice_int +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\l_keys_current_key_full_tl} +%\begin{macro}{\l_keys_current_key_name_tl} +% The current key name and the fully-qualified key are stored. +% \begin{macrocode} +\tl_new:N \l_keys_current_key_full_tl +\tl_new:N \l_keys_current_default_tl +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\l_keys_current_module_tl} +% The module name of the current module is stored here. +% \begin{macrocode} +\tl_new:N \l_keys_current_module_tl +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_keys_current_path_tl} +%\begin{macro}{\l_keys_default_path_tl} +%\begin{macro}{\l_keys_choice_path_tl} +% The current and default paths can be stored as tls. The default path +% is then initialised as the key root. +% \begin{macrocode} +\tl_new:N \l_keys_current_path_tl +\tl_new:N \l_keys_default_path_tl +\tl_set_eq:NN \l_keys_default_path_tl \c_keys_root_tl +\tl_new:N \l_keys_choice_path_tl +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\l_keys_current_value_toks} +% The current value is stored in a token register. +% \begin{macrocode} +\toks_new:N \l_keys_current_value_toks +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_keys_no_value_bool} +% To indicate that no value has been given. +% \begin{macrocode} +\bool_new:N \l_keys_no_value_bool +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_keys_success_bool} +% A switch for trying keys. +% \begin{macrocode} +\bool_new:N \l_keys_success_bool +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_keys_tmpa_tl} +% A scratch area. +% \begin{macrocode} +\tl_new:N \l_keys_tmpa_tl +% \end{macrocode} +%\end{macro} +% +%\subsubsection{Functions} +% +%\begin{macro}{\keys_manage:n} +%\begin{macro}{\keys_manage_quick:n} +%\begin{macro}{\keys_manage_internal:n} +%\begin{macro}[aux]{\keys_manage_aux:nn} +%\begin{macro}[aux]{\keys_manage_aux:Vn} +% The main key management macros both call the auxiliary function after +% setting up the parser. The expansion trick means a literal path is +% sent to the later function, and so the default path can be redefined. +% \begin{macrocode} +\cs_new:Nn \keys_manage:n { + \cs_set_eq:NN \keys_parse:n \KV_parse_space_removal_sanitize:n + \tl_clear:N \l_keys_current_module_tl + \keys_manage_internal:n {#1} +} +\cs_new:Nn \keys_manage_quick:n { + \cs_set_eq:NN \keys_parse:n \KV_parse_no_space_removal_no_sanitize:n + \tl_clear:N \l_keys_current_module_tl + \keys_manage_internal:n {#1} +} +\cs_new:Nn \keys_manage_internal:n { + \keys_manage_aux:Vn \l_keys_default_path_tl {#1} +} +\cs_new:Nn \keys_manage_aux:nn { + \tl_set_eq:NN \l_keys_default_path_tl \c_keys_root_tl + \keys_parse_list:n {#2} + \tl_set:Nn \l_keys_default_path_tl {#1} +} +\cs_generate_variant:Nn \keys_manage_aux:nn { Vn } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\begin{macro}{\keys_manage:nn} +%\begin{macro}{\keys_manage_quick:nn} +%\begin{macro}[aux]{\keys_manage_aux:nnn} +%\begin{macro}[aux]{\keys_manage_aux:Vnn} +% This version uses the same tricks but includes the path as a second +% argument. When setting lots of keys separately, this is a little +% faster than the key-based method. +% \begin{macrocode} +\cs_new:Nn \keys_manage:nn { + \cs_set_eq:NN \keys_parse:n \KV_parse_space_removal_sanitize:n + \keys_manage_aux:Vnn \l_keys_default_path_tl {#1} {#2} +} +\cs_new:Nn \keys_manage_quick:nn { + \cs_set_eq:NN \keys_parse:n \KV_parse_space_no_removal_no_sanitize:n + \keys_manage_aux:Vnn \l_keys_default_path_tl {#1} {#2} +} +\cs_new:Nn \keys_manage_aux:nnn { + \tl_set:Nn \l_keys_default_path_tl {#2} + \tl_clear:N \l_keys_current_module_tl + \keys_parse_list:n {#3} + \tl_set:Nn \l_keys_default_path_tl {#1} +} +\cs_generate_variant:Nn \keys_manage_aux:nnn { Vnn } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\subsubsection{Internal functions} +% +%\begin{macro}{\keys_bool_new:n} +% To create a new switch, which will be true (as the existence of the +% switch is the flag here). +% \begin{macrocode} +\cs_new_nopar:Nn \keys_bool_new:n { + \bool_new:c { \c_keys_cs_prefix_tl #1 } + \bool_set_true:c { \c_keys_cs_prefix_tl #1 } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\keys_bool_set:nN} +%\begin{macro}{\keys_bool_set:nnn} +% Boolean keys are created by using the fact that only \texttt{true} and +% \texttt{false} give the right result when looking for a setting +% function. A default is also set, so that the key name alone can be +% given. +% \begin{macrocode} +\cs_new_nopar:Nn \keys_bool_set:nN { + \keys_parse_list:n { + \c_keys_properties_path_tl /.code:n = { + \cs_if_exist:cTF { bool_ #1 _ ##1 :N } { + \use:c { bool_ #1 _ ##1 :N } #2 + }{ + \keys_error:nn { Boolean~expected } {##1} + } + }, + \l_keys_current_path_tl /.default:n = true + } +} +\cs_new_nopar:Nn \keys_bool_set:nnn { + \keys_parse_list:n { + \c_keys_properties_path_tl /.code:x = { + \exp_not:N \cs_if_exist:cTF { bool_ #1 _ ##1 :c } { + \exp_not:N \use:c { bool_ #1 _ ##1 :c } + { #2 \l_keys_current_module_tl #3 _bool } + }{ + \keys_error:nn { Boolean~expected } {##1} + } + }, + \l_keys_current_path_tl /.default:n = true + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\keys_bool_set_inverse:n} +%\begin{macro}{\keys_bool_set_inverse:nN} +%\begin{macro}{\keys_bool_set_inverse:nnn} +% To set keys with reversed logic, the basics can be done in the same +% way as for the standard switches. The only thing needed is a +% reversal of \texttt{true}/\texttt{false}. +% \begin{macrocode} +\cs_new_nopar:Nn \keys_bool_set_inverse:n { + \tl_if_eq:nnTF {#1} { true } { false } { true } +} +\cs_new_nopar:Nn \keys_bool_set_inverse:nN { + \keys_parse_list:n { + \c_keys_properties_path_tl /.code:n = { + \cs_if_exist:cTF { bool_ #1 _ ##1 :N } { + \use:c { bool_ #1 _ \keys_bool_set_inverse:n {##1} :N } #2 + }{ + \keys_error:nn { Boolean~expected } {##1} + } + }, + \l_keys_current_path_tl /.default:n = true + } +} +\cs_new_nopar:Nn \keys_bool_set_inverse:nnn { + \keys_parse_list:n { + \c_keys_properties_path_tl /.code:x = { + \exp_not:N \cs_if_exist:cTF { bool_ #1 _ ##1 :c } { + \exp_not:N \use:c { + bool_ #1 _ \exp_not:N \keys_bool_set_inverse:n {##1} :c + } { #2 \l_keys_current_module_tl #3 _bool } + }{ + \keys_error:nn { Boolean~expected } {##1} + } + }, + \l_keys_current_path_tl /.default:n = true + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\keys_check_exists:NN} +%\begin{macro}{\keys_check_exists:cN} +% A check function to avoid problems later. +% \begin{macrocode} +\cs_new_nopar:Nn \keys_check_exists:NN { + \cs_if_exist:NF #1 { + #2 #1 + } +} +\cs_generate_variant:Nn \keys_check_exists:NN { cN } +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\keys_choices_create:Nnn} +%\begin{macro}[aux]{\keys_choices_create_aux:n} +%\begin{macro}[aux]{\keys_choices_create_aux:x} +%\begin{macro}{\keys_choice_create:n} +% When making multiple choices, the code for each choice is the same. +% Only the path and counter need to be altered. +% \begin{macrocode} +\cs_new:Nn \keys_choices_create:Nnn { + \tl_set_eq:NN \l_keys_choice_path_tl \l_keys_current_path_tl + \int_zero:N \l_keys_current_choice_int + \use:c { keys_choices_create_aux: #1 } {#3} + \clist_map_function:nN {#2} \keys_choice_create:n + \keys_manage_internal:n { \l_keys_choice_path_tl /.expects_choice: } +} +\cs_new:Nn \keys_choices_create_aux:n { + \tl_set:Nn \l_keys_choice_code_tl { \exp_not:n {#1} } +} +\cs_new:Nn \keys_choices_create_aux:x { + \tl_set:Nn \l_keys_choice_code_tl {#1} +} +\cs_new_nopar:Nn \keys_choice_create:n { + \int_incr:N \l_keys_current_choice_int + \keys_parse_list:n { + \l_keys_choice_path_tl / #1 /.code:x = { + \exp_not:n { \int_set:Nn \l_keys_current_choice_int } + { \int_use:N \l_keys_current_choice_int } + \exp_not:n { \tl_set:Nn \l_keys_current_choice_tl } {#1} + \l_keys_choice_code_tl + } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\keys_clear_properties:n} +% To avoid problem on redefinition, all properties are removed. +% \begin{macrocode} +\cs_new_nopar:Nn \keys_clear_properties:n { + \keys_undefine:n { #1 /._cmd:w } + \keys_undefine:n { #1 /._default_tl } + \keys_undefine:n { #1 /._forbidden_bool } + \keys_undefine:n { #1 /._num_args_tl } + \keys_undefine:n { #1 /._required_bool } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\keys_default_add:} +% Copies the default value to the current one if needed. +% \begin{macrocode} +\cs_new_nopar:Nn \keys_default_add: { + \bool_if:NT \l_keys_no_value_bool { + \keys_if_exist:nT + { \l_keys_current_key_full_tl /._default_tl } { + \keys_toks_set:Nn \l_keys_current_value_toks + { \l_keys_current_key_full_tl /._default_tl } + \bool_set_false:N \l_keys_no_value_bool + } + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\keys_find_code_full:} +%\begin{macro}{\keys_find_code_name:} +% Two functions to find something to process the key value given. First, +% a search is made for either a command property for the key, or a +% function for the key itself. If that fails, the generic handlers are +% used after separating out the key name and key path. +% \begin{macrocode} +\cs_new_nopar:Nn \keys_find_code_full: { + \keys_if_cmd_exist:nTF { \l_keys_current_key_full_tl } { + \keys_use_cmd:n { \l_keys_current_key_full_tl } + }{ + \keys_if_exist:nTF { \l_keys_current_key_full_tl } { + \bool_if:NTF \l_keys_no_value_bool { + \keys_use:n { \l_keys_current_key_full_tl } + }{ + \keys_store:nx { \l_keys_current_key_full_tl } + { \toks_use:N \l_keys_current_value_toks } + } + }{ + \keys_find_code_name: + } + } +} +\cs_new_nopar:Nn \keys_find_code_name: { + \keys_separate_path: + \keys_if_cmd_exist:nTF + { \c_keys_properties_path_tl / \l_keys_current_key_name_tl } { + \keys_use_cmd:n + {\c_keys_properties_path_tl / \l_keys_current_key_name_tl} + }{ + \keys_if_cmd_exist:nTF + { \l_keys_current_path_tl / unknown } { + \keys_use_cmd:n { \l_keys_current_path_tl / unknown } + }{ + \keys_error:n { unknown~key } + } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}[TF]{\keys_if_cmd_exist:n} +% A dedicated check for the |._cmd:w| property key. +% \begin{macrocode} +\prg_new_conditional:Nnn \keys_if_cmd_exist:n {TF,T,F} { + \if_cs_exist:w \c_keys_cs_prefix_tl #1 /._cmd:w \cs_end: + \prg_return_true: + \else: + \prg_return_false: + \fi: +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}[TF]{\keys_if_exist:n} +% Check if a key exists without adding to the hash table. +% \begin{macrocode} +\prg_new_conditional:Nnn \keys_if_exist:n {TF,T,F} { + \if_cs_exist:w \c_keys_cs_prefix_tl #1 \cs_end: + \prg_return_true: + \else: + \prg_return_false: + \fi: +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}[TF]{\keys_if_value:n} +% Used for required and forbidden values. +% \begin{macrocode} +\prg_new_conditional:Nnn \keys_if_value:n {TF,T,F} { + \if_cs_exist:w + \c_keys_cs_prefix_tl \l_keys_current_key_full_tl /._ #1 _bool + \cs_end: + \prg_return_true: + \else: + \prg_return_false: + \fi: +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\keys_no_value_elt:n} +%\begin{macro}{\keys_value_elt:nn} +% The two functions passed to \pkg{l3keyval} to actually act on each +% key found. +% \begin{macrocode} +\cs_new:Nn \keys_no_value_elt:n { + \bool_set_true:N \l_keys_no_value_bool + \keys_process_elt:nn {#1} { } +} +\cs_new:Nn \keys_value_elt:nn { + \bool_set_false:N \l_keys_no_value_bool + \keys_process_elt:nn {#1} {#2} +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\keys_parse:n} +% The macro used to actually process the key--value input is taken from +% \pkg{l3keyval}. There are two possible options, and so at this +% stage the macro is simply reserved. +% \begin{macrocode} +\cs_new:Nn \keys_parse:n { \ERROR } +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\keys_parse_list:n} +% All of the management macros call this common parser. First, the key +% processing macros are defined, then the appropriate parser is called. +% \begin{macrocode} +\cs_new:Nn \keys_parse_list:n { + \cs_set_eq:NN \KV_key_value_elt:nn \keys_value_elt:nn + \cs_set_eq:NN \KV_key_no_value_elt:n \keys_no_value_elt:n + \keys_parse:n {#1} +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\keys_path_add:N} +%\begin{macro}{\keys_path_add:w} +%\begin{macro}[aux]{\keys_path_add_aux:w} +% The code to check for a path looks for a |/| at the start of the key. +% \begin{macrocode} +\cs_new_nopar:Nn \keys_path_add:N { + \exp_after:wN \keys_path_add:w #1 \q_stop +} +\cs_new_nopar:Npn \keys_path_add:w { + \exp_after:wN \peek_meaning:NTF \c_keys_root_tl { + \use_none_delimit_by_q_stop:w + }{ + \keys_path_add_aux:w + } +} +\cs_new_nopar:Npn \keys_path_add_aux:w #1 \q_stop { + \tl_set:Nx \l_keys_current_key_full_tl {\l_keys_default_path_tl #1} +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\keys_process_elt:nn} +%\begin{macro}[aux]{\keys_process_elt_aux:} +% The key processor starts by storing the given key name and value, and +% adding a path to the former if necessary. There is then potentially a +% need to fill in a default value before checking for required or +% forbidden values. +% \begin{macrocode} +\cs_new:Nn \keys_process_elt:nn { + \tl_set:Nx \l_keys_current_key_full_tl {#1} + \toks_set:Nn \l_keys_current_value_toks {#2} + \keys_path_add:N \l_keys_current_key_full_tl + \keys_default_add: + \keys_if_value:nTF { required } { + \bool_if:NTF \l_keys_no_value_bool { + \keys_error:n { value~required } + }{ + \keys_process_elt_aux: + } + }{ + \keys_process_elt_aux: + } +} +\cs_new:Nn \keys_process_elt_aux: { + \keys_if_value:nTF { forbidden } { + \bool_if:NTF \l_keys_no_value_bool { + \keys_find_code_full: + }{ + \keys_error:nn { value~forbidden } + { \toks_use:N \l_keys_current_value_toks } + } + }{ + \keys_find_code_full: + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\keys_separate_path:} +%\begin{macro}{\keys_separate_path:w} +% A simple piece of recursion to find the key name and path. +% \begin{macrocode} +\cs_new_nopar:Nn \keys_separate_path: { + \tl_clear:N \l_keys_current_path_tl + \exp_after:wN \keys_separate_path:w \l_keys_current_key_full_tl + / \q_stop +} +\cs_new_nopar:Npn \keys_separate_path:w / #1 / #2 \q_stop { + \tl_if_empty:nTF {#2} { + \tl_set:Nn \l_keys_current_key_name_tl {#1} + }{ + \tl_put_right:Nn \l_keys_current_path_tl { / #1 } + \keys_separate_path:w /#2 \q_stop + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\keys_set:NN} +%\begin{macro}{\keys_set:Nnn} +% Storage of data in outside of keys. +% \begin{macrocode} +\cs_new_nopar:Nn \keys_set:NN { + \keys_parse_list:n { + \c_keys_properties_path_tl /.code:n = { + #1 #2 {##1} + } + } +} +\cs_new_nopar:Nn \keys_set:Nnn { + \keys_parse_list:n { + \c_keys_properties_path_tl /.code:x = { + \exp_not:N #1 { #2 \l_keys_current_module_tl #3 } {##1} + } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\keys_set_cmd:nn} +%\begin{macro}{\keys_set_cmd:nx} +%\begin{macro}{\keys_set_cmd:nNn} +%\begin{macro}{\keys_set_cmd:nNx} +%\begin{macro}{._cmd:w} +%\begin{macro}{._num_args_tl} +% Creation of the key |._cmd:w| macros happens here. For the +% multiple-argument versions, the number of arguments is stored for +% use later on. +% \begin{macrocode} +\cs_new:Nn \keys_set_cmd:nn { + \keys_clear_properties:n {#1} + \cs_set:cpn { \c_keys_cs_prefix_tl #1 /._cmd:w } ##1 {#2} +} +\cs_new:Nn \keys_set_cmd:nx { + \keys_clear_properties:n {#1} + \cs_set:cpx { \c_keys_cs_prefix_tl #1 /._cmd:w } ##1 {#2} +} +\cs_new:Nn \keys_set_cmd:nNn { + \keys_clear_properties:n {#1} + \cs_generate_from_arg_count:cNnn { \c_keys_cs_prefix_tl #1 /._cmd:w } + \cs_set:Npn #2 {#3} + \keys_store:nn { #1 /._num_args_tl} {#2} +} +\cs_new:Nn \keys_set_cmd:nNx { + \keys_clear_properties:n {#1} + \cs_generate_from_arg_count:cNnn { \c_keys_cs_prefix_tl #1 /._cmd:w } + \cs_set:Npx #2 {#3} + \keys_store:nn { #1 /._num_args_tl} {#2} +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\keys_store:nn} +%\begin{macro}{\keys_store:nx} +% Direct storage of data in keys. +% \begin{macrocode} +\cs_new:Nn \keys_store:nn { + \tl_set:cn { \c_keys_cs_prefix_tl #1 } {#2} +} +\cs_new:Nn \keys_store:nx { + \tl_set:cx { \c_keys_cs_prefix_tl #1 } {#2} +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\keys_toks_set:Nn} +% Sets a toks to the content of a key. +% \begin{macrocode} +\cs_new_nopar:Nn \keys_toks_set:Nn { + \exp_args:NNv \toks_set:Nn #1 { \c_keys_cs_prefix_tl #2 } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\keys_try:} +% A function to look for the |._cmd:w| property of a key, and executes +% it if found. +% \begin{macrocode} +\cs_new_nopar:Nn \keys_try: { + \bool_set_false:N \l_keys_success_bool + \keys_if_cmd_exist:nT { \l_keys_current_path_tl } { + \bool_set_true:N \l_keys_success_bool + \bool_if:NT \l_keys_no_value_bool { + \keys_if_exist:nT + { \l_keys_current_path_tl /._default_tl } { + \keys_toks_set:Nn \l_keys_current_value_toks + { \l_keys_current_path_tl /._default_tl } + } + } + \cs_set_eq:NN \l_keys_current_key_full_tl \l_keys_current_path_tl + \keys_use_cmd:n { \l_keys_current_path_tl } + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\keys_undefine:n} +% To remove a key. +% \begin{macrocode} +\cs_new_nopar:Nn \keys_undefine:n { + \cs_set_eq:cN { \c_keys_cs_prefix_tl #1 } \c_undefined +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\keys_use:n} +% Use whatever is stored in a key. +% \begin{macrocode} +\cs_new_nopar:Nn \keys_use:n { + \use:c { \c_keys_cs_prefix_tl #1 } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\keys_use_cmd:n} +%\begin{macro}{\keys_use_cmd:nn} +%\begin{macro}[aux]{\keys_use_cmd_aux:nn} +%\begin{macro}[aux]{\keys_use_cmd_aux:w} +% Some care is needed when using command keys. For commands with +% multiple arguments a check is made in case none were given, and if +% so a series of empty values is given instead. +% \begin{macrocode} +\cs_new_nopar:Nn \keys_use_cmd:n { + \exp_args:Nno \keys_use_cmd:nn {#1} + { \toks_use:N \l_keys_current_value_toks } +} +\cs_new_nopar:Nn \keys_use_cmd:nn { + \keys_if_exist:nTF { #1 /._num_args_tl } { + \keys_use_cmd_aux:nn {#1} {#2} + }{ + \keys_use:n {#1/._cmd:w} {#2} + } +} +\cs_new_nopar:Nn \keys_use_cmd_aux:nn { + \tl_if_empty:nTF {#2} { + \cs_set:Npn \keys_use_cmd_aux:w { + \keys_use:n { #1 /._cmd:w } + } + \exp_after:wN \exp_after:wN \exp_after:wN \keys_use_cmd_aux:w + \cs:w + c_keys_ \keys_use:n { #1 /._num_args_tl } _empty_tl + \cs_end: + }{ + \keys_use:n { #1 /._cmd:w } #2 + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\subsubsection{Error handling code} +% +% The \LaTeX3 approach is to have named errors called separately and +% defined separately. To make life a little easier here, some custom +% functions are used to keep repetition down. +% +%\begin{macro}{\keys_msg_new:nn} +% To create new error messages, a utility function is created. +% \begin{macrocode} +\cs_new_nopar:Npn \keys_msg_new:nn #1 { + \msg_new:nnn { keys } {#1} +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\keys_error:n} +%\begin{macro}{\keys_error:nn} +% Utilities for using errors, which always have +% \cs{l_keys_current_key_full_tl} as the first argument. +% \begin{macrocode} +\cs_new_protected_nopar:Nn \keys_error:nn { + \msg_error:nnxx { keys } {#1} { \l_keys_current_key_full_tl } {#2} +} +\cs_new_protected_nopar:Nn \keys_error:n { + \msg_error:nnx { keys } {#1} { \l_keys_current_key_full_tl } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +% \begin{macrocode} +\keys_msg_new:nn + { unknown~key } + {The key `#1' is unknown and is being ignored.} +\keys_msg_new:nn + { value~required } + {The key `#1' requires a value\\% + and is being ignored.} +\keys_msg_new:nn + { value~forbidden } + {The key `#1' cannot taken a value:\\% + the given input `#2' is being ignored.} +\keys_msg_new:nn + { Boolean~expected } + {Key `#1' takes the Boolean values\\% + `true' and `false'~only.\\% + The given value `#2' is being ignored.} +\keys_msg_new:nn + { not_boolean } + {Key `#1' is not a Boolean key: you cannot create a complement.} +\keys_msg_new:nn + { unknown~choice } + {Choice `#2' unknown for key `#1':\\% + the key is being ignored.} +% \end{macrocode} +% +%\subsubsection{Property definitions} +% +%\begin{macro}{.code:n} +%\begin{macro}{.code:Nn} +% The \texttt{.code:n} and \texttt{.code:Nn} properties have to be +% defined directly. +% \begin{macrocode} +\keys_set_cmd:nn { \c_keys_properties_path_tl /.code:n } { + \keys_set_cmd:nn { \l_keys_current_path_tl } {#1} +} +\keys_set_cmd:nNn { \c_keys_properties_path_tl /.code:Nn } 2 { + \keys_set_cmd:nNn { \l_keys_current_path_tl } #1 {#2} +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +% The remaining definitions can all be carried out using the package +% itself. As category codes and spaces are not an issue here, the +% |_quick| version of \cs{keys_manage} is used. +% +% First, an error is created for unknown keys: this is done early to +% catch any internal errors. +% \begin{macrocode} +\keys_manage_quick:n { + \c_keys_errors_path_tl /unknown/.code:n = { + \keys_error:n { unknown~key } + } +} +% \end{macrocode} +% +%\begin{macro}{.code:x} +%\begin{macro}{.code:Nx} +% Fully-expanded versions of the basic \texttt{.code} properties. +% \begin{macrocode} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.code:x/.code:n = { + \keys_set_cmd:nx { \l_keys_current_path_tl } {#1} + }, + \c_keys_properties_path_tl /.code:Nx/.code:Nn = 2 { + \keys_set_cmd:nNx { \l_keys_current_path_tl } {#1} {#2} + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{.cd:} +% The change-directory property simply alters the value of the default +% path. +% \begin{macrocode} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.cd:/.code:n = { + \tl_set:Nx \l_keys_default_path_tl { \l_keys_current_path_tl / } + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{.value_forbidden:} +%\begin{macro}{._required_bool} +%\begin{macro}{.value_required:} +%\begin{macro}{._forbidden_bool} +% Values are required or forbidden by creating the appropriate flags. +% \begin{macrocode} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.value_required:/.code:n = { + \keys_bool_new:n { \l_keys_current_path_tl /._required_bool } + \keys_undefine:n { \l_keys_current_path_tl /._forbidden_bool } + }, + \c_keys_properties_path_tl /.value_forbidden:/.code:n = { + \keys_bool_new:n { \l_keys_current_path_tl /._forbidden_bool } + \keys_undefine:n { \l_keys_current_path_tl /._required_bool } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{.default:n} +%\begin{macro}{._default_tl} +% The default value for a key is stored in the |._default_tl| +% private property. +% \begin{macrocode} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.default:n/.code:n = { + \keys_store:nn { \l_keys_current_path_tl /._default_tl } {#1} + \keys_undefine:n { \l_keys_current_path_tl /._required_bool } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{.tl_set:N} +%\begin{macro}{.tl_set_x:N} +%\begin{macro}{.tl_gset:N} +%\begin{macro}{.tl_gset_x:N} +% Storage of the value in a tl, as given or expanded, local or global. +% \begin{macrocode} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.tl_set:N/.code:n = { + \keys_check_exists:NN #1 \tl_new:N + \keys_set:NN \tl_set:Nn #1 + }, + \c_keys_properties_path_tl /.tl_set_x:N/.code:n = { + \keys_check_exists:NN #1 \tl_new:N + \keys_set:NN \tl_set:Nx #1 + }, + \c_keys_properties_path_tl /.tl_gset:N/.code:n = { + \keys_check_exists:NN #1 \tl_new:N + \keys_set:NN \tl_gset:Nn #1 + }, + \c_keys_properties_path_tl /.tl_gset_x:N/.code:n = { + \keys_check_exists:NN #1 \tl_new:N + \keys_set:NN \tl_gset:Nx #1 + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{.int_set:N} +%\begin{macro}{.int_gset:N} +%\begin{macro}{.skip_set:N} +%\begin{macro}{.skip_gset:N} +%\begin{macro}{.toks_set:N} +%\begin{macro}{.toks_gset:N} +% For int, skip and toks storage, no expansion to worry about. +% \begin{macrocode} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.int_set:N/.code:n = { + \keys_check_exists:NN #1 \int_new:N + \keys_set:NN \int_set:Nn #1 + }, + \c_keys_properties_path_tl /.int_gset:N/.code:n = { + \keys_check_exists:NN #1 \int_new:N + \keys_set:NN \int_gset:Nn #1 + }, + \c_keys_properties_path_tl /.skip_set:N/.code:n = { + \keys_check_exists:NN #1 \skip_new:N + \keys_set:NN \skip_set:Nn #1 + }, + \c_keys_properties_path_tl /.skip_gset:N/.code:n = { + \keys_check_exists:NN #1 \skip_new:N + \keys_set:NN \skip_gset:Nn #1 + }, + \c_keys_properties_path_tl /.toks_set:N/.code:n = { + \keys_check_exists:NN #1 \toks_new:N + \keys_set:NN \toks_set:Nn #1 + }, + \c_keys_properties_path_tl /.toks_gset:N/.code:n = { + \keys_check_exists:NN #1 \toks_new:N + \keys_set:NN \toks_gset:Nn #1 + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +% The prefix for the current module is needed when storing material +% by csname. +% \begin{macrocode} +\keys_manage_quick:n { + \c_keys_utilities_path_tl /current_module:n/.code:n = { + \tl_if_empty:nTF {#1} { + \tl_clear:N \l_keys_current_module_tl + }{ + \tl_set:Nn \l_keys_current_module_tl { #1 _ } + } + } +} +% \end{macrocode} +% +%\begin{macro}{.tl_set:n} +%\begin{macro}{.tl_set_x:n} +%\begin{macro}{.tl_gset:n} +%\begin{macro}{.tl_gset_x:n} +%\begin{macro}{.int_set:n} +%\begin{macro}{.int_gset:n} +%\begin{macro}{.skip_set:n} +%\begin{macro}{.skip_gset:n} +%\begin{macro}{.toks_set:n} +%\begin{macro}{.toks_gset:n} +% With the module available, storage properties that only need the +% unique part of the variable name are created. +% \begin{macrocode} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.tl_set:n/.code:n = { + \keys_check_exists:cN { l_ #1 _tl } \tl_new:N + \keys_set:Nnn \tl_set:cn { l_ } { #1 _tl } + }, + \c_keys_properties_path_tl /.tl_set_x:n/.code:n = { + \keys_check_exists:cN { l_ #1 _tl } \tl_new:N + \keys_set:Nnn \tl_set:cx { l_ } { #1 _tl } + }, + \c_keys_properties_path_tl /.tl_gset:n/.code:n = { + \keys_check_exists:cN { g_ #1 _tl } \tl_new:N + \keys_set:Nnn \tl_gset:cn { g_ } { #1 _tl } + }, + \c_keys_properties_path_tl /.tl_gset_x:n/.code:n = { + \keys_check_exists:cN { g_ #1 _tl } \tl_new:N + \keys_set:Nnn \tl_gset:cx { g_ } { #1 _tl } + }, + \c_keys_properties_path_tl /.int_set:n/.code:n = { + \keys_check_exists:cN { l_ #1 _int } \int_new:N + \keys_set:Nnn \int_set:cn { l_ } { #1 _int } + }, + \c_keys_properties_path_tl /.int_gset:n/.code:n = { + \keys_check_exists:cN { g_ #1 _int } \int_new:N + \keys_set:Nnn \int_gset:cn { g_ } { #1 _int } + }, + \c_keys_properties_path_tl /.skip_set:n/.code:n = { + \keys_check_exists:cN { l_ #1 _skip } \skip_new:N + \keys_set:Nnn \skip_set:cn { l_ } { #1 _skip } + }, + \c_keys_properties_path_tl /.skip_gset:n/.code:n = { + \keys_check_exists:cN { g_ #1 _skip } \skip_new:N + \keys_set:Nnn \skip_gset:cn { g_ } { #1 _skip } + }, + \c_keys_properties_path_tl /.toks_set:n/.code:n = { + \keys_check_exists:cN { g_ #1 _toks } \toks_new:N + \keys_set:Nnn \toks_set:cn { l_ } { #1 _toks } + }, + \c_keys_properties_path_tl /.toks_gset:n/.code:n = { + \keys_check_exists:cN { g_ #1 _toks } \toks_new:N + \keys_set:Nnn \toks_gset:cn { g_ } { #1 _toks } + }, +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{.bool_set:N} +%\begin{macro}{.bool_gset:N} +%\begin{macro}{.bool_set:n} +%\begin{macro}{.bool_gset:n} +% The properties for switches look similar, although internally things +% are rather different. +% \begin{macrocode} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.bool_set:N/.code:n = { + \keys_bool_set:nN { set } #1 + }, + \c_keys_properties_path_tl /.bool_gset:N/.code:n = { + \keys_bool_set:nN { gset } #1 + }, + \c_keys_properties_path_tl /.bool_set:n/.code:n = { + \keys_bool_set:nnn { set } { l_ } { #1 } + }, + \c_keys_properties_path_tl /.bool_gset:n/.code:n = { + \keys_bool_set:nnn { gset } { g_ } { #1 } + }, +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{.bool_set_inverse:N} +%\begin{macro}{.bool_gset_inverse:N} +%\begin{macro}{.bool_set_inverse:n} +%\begin{macro}{.bool_gset_inverse:n} +% The inverse versions of the switches are handled in the same way +% here. +% \begin{macrocode} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.bool_set_inverse:N/.code:n = { + \keys_bool_set_inverse:nN { set } #1 + }, + \c_keys_properties_path_tl /.bool_gset_inverse:N/.code:n = { + \keys_bool_set_inverse:nN { gset } #1 + }, + \c_keys_properties_path_tl /.bool_set_inverse:n/.code:n = { + \keys_bool_set_inverse:nnn { set } { l_ } { #1 } + }, + \c_keys_properties_path_tl /.bool_gset_inverse:n/.code:n = { + \keys_bool_set_inverse:nnn { gset } { g_ } { #1 } + }, +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{.expects_choice:} +% Multiple choice keys are created by searching sub-keys. So the +% code to make a key into a multiple choice is quite simple. +% \begin{macrocode} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.expects_choice:/.code:n = { + \keys_manage_internal:n { + \l_keys_current_path_tl /.cd:, + .code:n = { + \tl_set:Nn \l_keys_current_choice_tl {##1} + \int_zero:N \l_keys_current_choice_int + \exp_args:No \keys_parse_list:n + { \l_keys_current_key_full_tl / ##1 } + }, + unknown/.code:n = { + \keys_error:nn { unknown~choice } + { \l_keys_current_key_name_tl } + } + } + }, +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{.create_choices:nn} +%\begin{macro}{.create_choices:nx} +% Creating choices as a block. +% \begin{macrocode} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.create_choices:nn/.code:Nn = 2 { + \keys_choices_create:Nnn n {#1} {#2} + }, + \c_keys_properties_path_tl /.create_choices:nx/.code:Nn = 2 { + \keys_choices_create:Nnn x {#1} {#2} + }, +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{.use_keys:n} +%\begin{macro}{.use_keys:x} +%\begin{macro}{.use_keys:Nn} +%\begin{macro}{.use_keys:Nx} +% Keys calling other keys is actually quite easy. +% \begin{macrocode} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.use_keys:n/.code:n = { + \keys_manage_internal:n { + \l_keys_current_path_tl /.code:n = { \keys_parse_list:n {#1} } + } + }, + \c_keys_properties_path_tl /.use_keys:x/.code:n = { + \keys_manage_internal:n { + \l_keys_current_path_tl /.code:x = { + \exp_not:N \keys_parse_list:n {#1} + } + } + }, + \c_keys_properties_path_tl /.use_keys:Nn/.code:Nn = 2 { + \keys_manage_internal:n { + \l_keys_current_path_tl /.code:Nn = #1 { \keys_parse_list:n {#2} } + } + }, + \c_keys_properties_path_tl /.use_keys:Nx/.code:Nn = 2 { + \keys_manage_internal:n { + \l_keys_current_path_tl /.code:Nx = + #1 { \exp_not:N \keys_parse_list:n {#2} } + } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{.try:n} +%\begin{macro}{.retry:n} +% For attempting to set keys without assuming they exist. +% \begin{macrocode} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.try:n/.code:n = { \keys_try: }, + \c_keys_properties_path_tl /.retry:n/.code:n = { + \bool_if:NF \l_keys_success_bool { \keys_try: } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{.show_code:} +%\begin{macro}{.show_key:} +% Finally, two keys for debugging problems. +% \begin{macrocode} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.show_code:/.code:n = { + \cs_show:c { + \c_keys_cs_prefix_tl \l_keys_current_path_tl /._cmd:w + } + }, + \c_keys_properties_path_tl /.show_key:/.code:n = { + \cs_show:c { \c_keys_cs_prefix_tl \l_keys_current_path_tl } + } +} +%</package> +% \end{macrocode} +%\end{macro} +%\end{macro} +% +% \end{implementation} diff --git a/Master/texmf-dist/source/latex/keys3/keys3.ins b/Master/texmf-dist/source/latex/keys3/keys3.ins new file mode 100644 index 00000000000..30b04080e3a --- /dev/null +++ b/Master/texmf-dist/source/latex/keys3/keys3.ins @@ -0,0 +1,89 @@ +%%
+%% This is file `keys3.ins',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% keys3.dtx (with options: `install')
+%% ---------------------------------------------------------------
+%% The keys3 package --- Key management for LaTeX3
+%% Maintained by Joseph Wright
+%% E-mail: joseph.wright@morningstar2.co.uk
+%% Released under the LaTeX Project Public License v1.3c or later
+%% See http://www.latex-project.org/lppl.txt
+%% ---------------------------------------------------------------
+%%
+%% EXPERIMENTAL CODE
+%%
+%% Do not distribute this file without also distributing the
+%% source files specified above.
+%%
+%% Do not distribute a modified version of this file.
+%%
+\input docstrip.tex
+\keepsilent
+\askforoverwritefalse
+\preamble
+---------------------------------------------------------------
+The keys3 package --- Key management for LaTeX3
+Maintained by Joseph Wright
+E-mail: joseph.wright@morningstar2.co.uk
+Released under the LaTeX Project Public License v1.3c or later
+See http://www.latex-project.org/lppl.txt
+---------------------------------------------------------------
+
+EXPERIMENTAL CODE
+
+Do not distribute this file without also distributing the
+source files specified above.
+
+Do not distribute a modified version of this file.
+
+\endpreamble
+\postamble
+
+Copyright (C) 2008-2009 by
+ Joseph Wright <joseph.wright@morningstar2.co.uk>
+
+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 work is "maintained" (as per LPPL maintenance status) by
+ Joseph Wright.
+
+This work consists of the file keys3.dtx
+ and the derived files keys3.pdf,
+ keys3.sty and
+ keys3.ins.
+
+\endpostamble
+\usedir{tex/latex/keys3}
+\generate{
+ \file{\jobname.sty}{\from{\jobname.dtx}{package}}
+}
+\endbatchfile
+%%
+%% Copyright (C) 2008-2009 by
+%% Joseph Wright <joseph.wright@morningstar2.co.uk>
+%%
+%% 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 work is "maintained" (as per LPPL maintenance status) by
+%% Joseph Wright.
+%%
+%% This work consists of the file keys3.dtx
+%% and the derived files keys3.pdf,
+%% keys3.sty and
+%% keys3.ins.
+%%
+%%
+%% End of file `keys3.ins'.
diff --git a/Master/texmf-dist/source/latex/keys3/keys3opts2.dtx b/Master/texmf-dist/source/latex/keys3/keys3opts2.dtx new file mode 100644 index 00000000000..5aa9e8cce08 --- /dev/null +++ b/Master/texmf-dist/source/latex/keys3/keys3opts2.dtx @@ -0,0 +1,256 @@ +%\iffalse +% !TEX program = pdflatex +% !TEX encoding = ISO-8859-1 +%<*internal> +\iffalse +%</internal> +%<*readme> +--------------------------------------------------------------- +The keys3opts2 package --- Using keys3 for LaTeX2e options +Maintained by Joseph Wright +E-mail: joseph.wright@morningstar2.co.uk +Released under the LaTeX Project Public License v1.3c or later +See http://www.latex-project.org/lppl.txt +--------------------------------------------------------------- + +The keys3 package is an experimental implementation of key +management for LaTeX3. The entire package is written in +expl3 code rather than in traditional TeX/LaTeX. The +keys3opts2 package provides a mechanism to allow load-time +option processed using keys3 in LaTeX2e. + +%</readme> +%<*internal> +\fi +\def\nameofplainTeX{plain} +\ifx\fmtname\nameofplainTeX\else + \expandafter\begingroup +\fi +%</internal> +%<*install> +\input docstrip.tex +\keepsilent +\askforoverwritefalse +\preamble +--------------------------------------------------------------- +The keys3opts2 package --- Using keys3 for LaTeX2e options +Maintained by Joseph Wright +E-mail: joseph.wright@morningstar2.co.uk +Released under the LaTeX Project Public License v1.3c or later +See http://www.latex-project.org/lppl.txt +--------------------------------------------------------------- + +EXPERIMENTAL CODE + +Do not distribute this file without also distributing the +source files specified above. + +Do not distribute a modified version of this file. + +\endpreamble +\postamble + +Copyright (C) 2008-2009 by + Joseph Wright <joseph.wright@morningstar2.co.uk> + +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 work is "maintained" (as per LPPL maintenance status) by + Joseph Wright. + +This work consists of the file keys3opts2.dtx + and the derived files keys3opts2.pdf, + keys3opts2.sty and + keys3opts2.ins. + +\endpostamble +\usedir{tex/latex/keys3} +\generate{ + \file{\jobname.sty}{\from{\jobname.dtx}{package}} +} +%</install> +%<install>\endbatchfile +%<*internal> +\usedir{source/latex/keys3} +\generate{ + \file{\jobname.ins}{\from{\jobname.dtx}{install}} +} +\ifx\fmtname\nameofplainTeX + \expandafter\endbatchfile +\else + \expandafter\endgroup +\fi +%</internal> +%<*driver|package> +\RequirePackage{l3names} +\GetIdInfo$Id: keys3opts2.dtx 93 2009-05-03 20:34:46Z josephwright $ + {Using keys3 for LaTeX2e options} +%</driver|package> +%\fi +%\iffalse +%<*driver> +%\fi +\ProvidesFile{\filename.\filenameext} + [\filedate\space v\fileversion\space\filedescription] +%\iffalse +\documentclass[full]{l3doc} +\begin{document} + \DocInput{\filename.\filenameext} +\end{document} +%</driver> +% \fi +% +% \title{The \textsf{keys3opts2} package^^A +% \thanks{This file has version number \fileversion, last +% revised \filedate.}\\ +% Using \textsf{keys3} for \LaTeXe\ options} +% \author{Joseph Wright^^A +% \thanks{E-mail: joseph.wright@morningstar2.co.uk}} +% \date{\filedate} +% \maketitle +% +%\section{Package options} +% +% The methods that \LaTeX3 will use to process package options are not +% clear at the present time. However, in order to fully test the +% \pkg{expl3} bundle fully, it is useful to be able to work with +% the \LaTeXe\ system but using \LaTeX3 methods as far as possible. +% +% The \pkg{keys3} package provides an experimental method for +% managing key--value input using \pkg{expl3} syntax. It is +% self-contained and does not use any \LaTeXe methods. On the other +% hand, \pkg{keys3opts2} is intended as a ``bridge'' between the +% \LaTeXe\ kernel and \textsf{keys3}. It allows keys to be created +% using \pkg{keys3} and processed by \LaTeXe\ as package or class +% options. +% +%\subsection{functions} +% +% \begin{function}{\keys_options_ltx:n} +% \begin{syntax} +% "\keys_options_ltx:n" <module> +% \end{syntax} +% The only macro for outside use. Processes the current option list +% using the currently defined keys, checking if they exist for +% <module>. +% \end{function} +% +% \begin{function}{ +% \keys_options_ltx_cls:n| +% \keys_options_ltx_pkg:n +% } +% \begin{syntax} +% "\keys_options_ltx_cls:n" <option> +% \end{syntax} +% Helper macros for processing class and package options, +% respectively. +% \end{function} +% +% \begin{function}{\keys_options_ltx_strip_eq:w} +% \begin{syntax} +% "\keys_options_ltx_strip_eq:w" <option> "\q_stop" +% \end{syntax} +% Used to strip ``\texttt{=}'' out of options. +% \end{function} +% +% \begin{variable}{\l_keys_options_ltx_clist} +% Storage area for option list. +% \end{variable} +% +%\subsection{Implementation} +% +% Almost everything here is based heavily on \pkg{pgfopts}, which is +% itself a port of the appropriate code from \pkg{kvoptions} to work +% with \pkg{pgfkeys}. +% +% As this package is an add-on to \pkg{keys3}, the same internal +% module name (|\keys_|) is used here as in the main package. The lead +% off as usual. +% \begin{macrocode} +%<*package> +\ProvidesExplPackage + {\filename}{\filedate}{\fileversion}{\filedescription} +\RequirePackage{keys3} +% \end{macrocode} +% +%\begin{macro}{\l_keys_options_ltx_clist} +% A simple storage area. +% \begin{macrocode} +\clist_new:N \l_keys_options_ltx_clist +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\keys_options_ltx:n} +% As this is a minimal testing package, a lot of the complexity of the +% normal \LaTeX\ options is ignored. Here, the package insists a path +% is given for the keys. First, a path may need to be added to the +% argument given. The path we need to process is then stored in +% \cs{l_keys_current_key_tl}. +% \begin{macrocode} +\cs_new:Nn \keys_options_ltx:n { + \tl_set:Nx \l_keys_current_key_tl {#1} + \keys_path_add:N \l_keys_current_key_tl + \clist_clear:N \l_keys_options_ltx_clist + \cs_if_eq:NNTF \@currext \@clsextension { + \cs_if_free:cF { opt@ \@currname . \@currext } { + \clist_map_function:cN { opt@ \@currname . \@currext } + \keys_options_ltx_cls:n + } + }{ + \cs_if_free:NF \@classoptionslist { + \clist_map_function:NN \@classoptionslist \keys_options_ltx_pkg:n + } + \cs_if_free:cF { opt@ \@currname . \@currext } { + \exp_args:NNc \clist_concat:NNN \l_keys_options_ltx_clist + { opt@ \@currname . \@currext } \l_keys_options_ltx_clist + } + } + \clist_put_left:Nn \l_keys_options_ltx_clist { #1 /.cd: } + \exp_args:NV \keys_manage:n \l_keys_options_ltx_clist + \AtEndOfPackage { \cs_set_eq:NN \@unprocessedoptions \scan_stop: } +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\keys_options_ltx_cls:n} +% This macro checks if the current class option is a known key. To do +% that, any ``\texttt{=}'' part has to be removed first. +% \begin{macrocode} +\cs_new:Nn \keys_options_ltx_cls:n { + \keys_if_cmd_exist:nTF { + \l_keys_current_key_tl / \keys_options_ltx_strip_eq:w #1 = \q_stop + }{ + \clist_put_right:Nn \l_keys_options_ltx_clist {#1} + }{ + \clist_put_right:Nn \@unusedoptionlist {#1} + } +} +% \end{macrocode} +%\end{macro} +%\begin{macro}{\keys_options_ltx_pkg:n} +% For packages, options need to be removed from the global list. +% \begin{macrocode} +\cs_new:Nn \keys_options_ltx_pkg:n { + \keys_if_cmd_really_exist:nT { + \l_keys_current_key_tl / \keys_options_ltx_strip_eq:w #1 = \q_stop + }{ + \clist_put_right:Nn \l_keys_options_ltx_clist {#1} + \clist_remove_element:Nn \@unusedoptionlist {#1} + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\keys_options_ltx_strip_eq:w} +% A simple method to remove an equals sign plus any trailing data. +% \begin{macrocode} +\cs_new:Npn \keys_options_ltx_strip_eq:w #1 = #2 \q_stop {#1} +%</package> +% \end{macrocode} +%\end{macro} +% +%\Finale diff --git a/Master/texmf-dist/source/latex/keys3/keys3opts2.ins b/Master/texmf-dist/source/latex/keys3/keys3opts2.ins new file mode 100644 index 00000000000..b49c3a57e4f --- /dev/null +++ b/Master/texmf-dist/source/latex/keys3/keys3opts2.ins @@ -0,0 +1,89 @@ +%%
+%% This is file `keys3opts2.ins',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% keys3opts2.dtx (with options: `install')
+%% ---------------------------------------------------------------
+%% The keys3opts2 package --- Using keys3 for LaTeX2e options
+%% Maintained by Joseph Wright
+%% E-mail: joseph.wright@morningstar2.co.uk
+%% Released under the LaTeX Project Public License v1.3c or later
+%% See http://www.latex-project.org/lppl.txt
+%% ---------------------------------------------------------------
+%%
+%% EXPERIMENTAL CODE
+%%
+%% Do not distribute this file without also distributing the
+%% source files specified above.
+%%
+%% Do not distribute a modified version of this file.
+%%
+\input docstrip.tex
+\keepsilent
+\askforoverwritefalse
+\preamble
+---------------------------------------------------------------
+The keys3opts2 package --- Using keys3 for LaTeX2e options
+Maintained by Joseph Wright
+E-mail: joseph.wright@morningstar2.co.uk
+Released under the LaTeX Project Public License v1.3c or later
+See http://www.latex-project.org/lppl.txt
+---------------------------------------------------------------
+
+EXPERIMENTAL CODE
+
+Do not distribute this file without also distributing the
+source files specified above.
+
+Do not distribute a modified version of this file.
+
+\endpreamble
+\postamble
+
+Copyright (C) 2008-2009 by
+ Joseph Wright <joseph.wright@morningstar2.co.uk>
+
+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 work is "maintained" (as per LPPL maintenance status) by
+ Joseph Wright.
+
+This work consists of the file keys3opts2.dtx
+ and the derived files keys3opts2.pdf,
+ keys3opts2.sty and
+ keys3opts2.ins.
+
+\endpostamble
+\usedir{tex/latex/keys3}
+\generate{
+ \file{\jobname.sty}{\from{\jobname.dtx}{package}}
+}
+\endbatchfile
+%%
+%% Copyright (C) 2008-2009 by
+%% Joseph Wright <joseph.wright@morningstar2.co.uk>
+%%
+%% 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 work is "maintained" (as per LPPL maintenance status) by
+%% Joseph Wright.
+%%
+%% This work consists of the file keys3opts2.dtx
+%% and the derived files keys3opts2.pdf,
+%% keys3opts2.sty and
+%% keys3opts2.ins.
+%%
+%%
+%% End of file `keys3opts2.ins'.
diff --git a/Master/texmf-dist/tex/latex/keys3/keys3.sty b/Master/texmf-dist/tex/latex/keys3/keys3.sty new file mode 100644 index 00000000000..140e038463e --- /dev/null +++ b/Master/texmf-dist/tex/latex/keys3/keys3.sty @@ -0,0 +1,686 @@ +%% +%% This is file `keys3.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% keys3.dtx (with options: `package') +%% --------------------------------------------------------------- +%% The keys3 package --- Key management for LaTeX3 +%% Maintained by Joseph Wright +%% E-mail: joseph.wright@morningstar2.co.uk +%% Released under the LaTeX Project Public License v1.3c or later +%% See http://www.latex-project.org/lppl.txt +%% --------------------------------------------------------------- +%% +%% EXPERIMENTAL CODE +%% +%% Do not distribute this file without also distributing the +%% source files specified above. +%% +%% Do not distribute a modified version of this file. +%% +\RequirePackage{expl3} +\GetIdInfo$Id: keys3.dtx 101 2009-06-10 12:16:20Z josephwright $ + {Key management for LaTeX3} +\ProvidesExplPackage + {\filename}{\filedate}{\fileversion}{\filedescription} +\tl_new:cn { c_keys_0_empty_tl } {} +\tl_new:cn { c_keys_1_empty_tl } { {} } +\tl_new:cn { c_keys_2_empty_tl } { {} {} } +\tl_new:cn { c_keys_3_empty_tl } { {} {} {} } +\tl_new:cn { c_keys_4_empty_tl } { {} {} {} {} } +\tl_new:cn { c_keys_5_empty_tl } { {} {} {} {} {} } +\tl_new:cn { c_keys_6_empty_tl } { {} {} {} {} {} {} } +\tl_new:cn { c_keys_7_empty_tl } { {} {} {} {} {} {} {} } +\tl_new:cn { c_keys_8_empty_tl } { {} {} {} {} {} {} {} {} } +\tl_new:cn { c_keys_9_empty_tl } { {} {} {} {} {} {} {} {} {} } +\tl_new:Nn \c_keys_cs_prefix_tl { keys-root } +\tl_new:Nn \c_keys_errors_path_tl { /keys/errors } +\tl_new:Nn \c_keys_properties_path_tl { /keys/properties } +\tl_new:Nn \c_keys_utilities_path_tl { /keys } +\tl_new:Nn \c_keys_root_tl { / } +\tl_new:N \l_keys_choice_code_tl +\tl_new:N \l_keys_current_choice_tl +\int_new:N \l_keys_current_choice_int +\tl_new:N \l_keys_current_key_full_tl +\tl_new:N \l_keys_current_default_tl +\tl_new:N \l_keys_current_module_tl +\tl_new:N \l_keys_current_path_tl +\tl_new:N \l_keys_default_path_tl +\tl_set_eq:NN \l_keys_default_path_tl \c_keys_root_tl +\tl_new:N \l_keys_choice_path_tl +\toks_new:N \l_keys_current_value_toks +\bool_new:N \l_keys_no_value_bool +\bool_new:N \l_keys_success_bool +\tl_new:N \l_keys_tmpa_tl +\cs_new:Nn \keys_manage:n { + \cs_set_eq:NN \keys_parse:n \KV_parse_space_removal_sanitize:n + \tl_clear:N \l_keys_current_module_tl + \keys_manage_internal:n {#1} +} +\cs_new:Nn \keys_manage_quick:n { + \cs_set_eq:NN \keys_parse:n \KV_parse_no_space_removal_no_sanitize:n + \tl_clear:N \l_keys_current_module_tl + \keys_manage_internal:n {#1} +} +\cs_new:Nn \keys_manage_internal:n { + \keys_manage_aux:Vn \l_keys_default_path_tl {#1} +} +\cs_new:Nn \keys_manage_aux:nn { + \tl_set_eq:NN \l_keys_default_path_tl \c_keys_root_tl + \keys_parse_list:n {#2} + \tl_set:Nn \l_keys_default_path_tl {#1} +} +\cs_generate_variant:Nn \keys_manage_aux:nn { Vn } +\cs_new:Nn \keys_manage:nn { + \cs_set_eq:NN \keys_parse:n \KV_parse_space_removal_sanitize:n + \keys_manage_aux:Vnn \l_keys_default_path_tl {#1} {#2} +} +\cs_new:Nn \keys_manage_quick:nn { + \cs_set_eq:NN \keys_parse:n \KV_parse_space_no_removal_no_sanitize:n + \keys_manage_aux:Vnn \l_keys_default_path_tl {#1} {#2} +} +\cs_new:Nn \keys_manage_aux:nnn { + \tl_set:Nn \l_keys_default_path_tl {#2} + \tl_clear:N \l_keys_current_module_tl + \keys_parse_list:n {#3} + \tl_set:Nn \l_keys_default_path_tl {#1} +} +\cs_generate_variant:Nn \keys_manage_aux:nnn { Vnn } +\cs_new_nopar:Nn \keys_bool_new:n { + \bool_new:c { \c_keys_cs_prefix_tl #1 } + \bool_set_true:c { \c_keys_cs_prefix_tl #1 } +} +\cs_new_nopar:Nn \keys_bool_set:nN { + \keys_parse_list:n { + \c_keys_properties_path_tl /.code:n = { + \cs_if_exist:cTF { bool_ #1 _ ##1 :N } { + \use:c { bool_ #1 _ ##1 :N } #2 + }{ + \keys_error:nn { Boolean~expected } {##1} + } + }, + \l_keys_current_path_tl /.default:n = true + } +} +\cs_new_nopar:Nn \keys_bool_set:nnn { + \keys_parse_list:n { + \c_keys_properties_path_tl /.code:x = { + \exp_not:N \cs_if_exist:cTF { bool_ #1 _ ##1 :c } { + \exp_not:N \use:c { bool_ #1 _ ##1 :c } + { #2 \l_keys_current_module_tl #3 _bool } + }{ + \keys_error:nn { Boolean~expected } {##1} + } + }, + \l_keys_current_path_tl /.default:n = true + } +} +\cs_new_nopar:Nn \keys_bool_set_inverse:n { + \tl_if_eq:nnTF {#1} { true } { false } { true } +} +\cs_new_nopar:Nn \keys_bool_set_inverse:nN { + \keys_parse_list:n { + \c_keys_properties_path_tl /.code:n = { + \cs_if_exist:cTF { bool_ #1 _ ##1 :N } { + \use:c { bool_ #1 _ \keys_bool_set_inverse:n {##1} :N } #2 + }{ + \keys_error:nn { Boolean~expected } {##1} + } + }, + \l_keys_current_path_tl /.default:n = true + } +} +\cs_new_nopar:Nn \keys_bool_set_inverse:nnn { + \keys_parse_list:n { + \c_keys_properties_path_tl /.code:x = { + \exp_not:N \cs_if_exist:cTF { bool_ #1 _ ##1 :c } { + \exp_not:N \use:c { + bool_ #1 _ \exp_not:N \keys_bool_set_inverse:n {##1} :c + } { #2 \l_keys_current_module_tl #3 _bool } + }{ + \keys_error:nn { Boolean~expected } {##1} + } + }, + \l_keys_current_path_tl /.default:n = true + } +} +\cs_new_nopar:Nn \keys_check_exists:NN { + \cs_if_exist:NF #1 { + #2 #1 + } +} +\cs_generate_variant:Nn \keys_check_exists:NN { cN } +\cs_new:Nn \keys_choices_create:Nnn { + \tl_set_eq:NN \l_keys_choice_path_tl \l_keys_current_path_tl + \int_zero:N \l_keys_current_choice_int + \use:c { keys_choices_create_aux: #1 } {#3} + \clist_map_function:nN {#2} \keys_choice_create:n + \keys_manage_internal:n { \l_keys_choice_path_tl /.expects_choice: } +} +\cs_new:Nn \keys_choices_create_aux:n { + \tl_set:Nn \l_keys_choice_code_tl { \exp_not:n {#1} } +} +\cs_new:Nn \keys_choices_create_aux:x { + \tl_set:Nn \l_keys_choice_code_tl {#1} +} +\cs_new_nopar:Nn \keys_choice_create:n { + \int_incr:N \l_keys_current_choice_int + \keys_parse_list:n { + \l_keys_choice_path_tl / #1 /.code:x = { + \exp_not:n { \int_set:Nn \l_keys_current_choice_int } + { \int_use:N \l_keys_current_choice_int } + \exp_not:n { \tl_set:Nn \l_keys_current_choice_tl } {#1} + \l_keys_choice_code_tl + } + } +} +\cs_new_nopar:Nn \keys_clear_properties:n { + \keys_undefine:n { #1 /._cmd:w } + \keys_undefine:n { #1 /._default_tl } + \keys_undefine:n { #1 /._forbidden_bool } + \keys_undefine:n { #1 /._num_args_tl } + \keys_undefine:n { #1 /._required_bool } +} +\cs_new_nopar:Nn \keys_default_add: { + \bool_if:NT \l_keys_no_value_bool { + \keys_if_exist:nT + { \l_keys_current_key_full_tl /._default_tl } { + \keys_toks_set:Nn \l_keys_current_value_toks + { \l_keys_current_key_full_tl /._default_tl } + \bool_set_false:N \l_keys_no_value_bool + } + } +} +\cs_new_nopar:Nn \keys_find_code_full: { + \keys_if_cmd_exist:nTF { \l_keys_current_key_full_tl } { + \keys_use_cmd:n { \l_keys_current_key_full_tl } + }{ + \keys_if_exist:nTF { \l_keys_current_key_full_tl } { + \bool_if:NTF \l_keys_no_value_bool { + \keys_use:n { \l_keys_current_key_full_tl } + }{ + \keys_store:nx { \l_keys_current_key_full_tl } + { \toks_use:N \l_keys_current_value_toks } + } + }{ + \keys_find_code_name: + } + } +} +\cs_new_nopar:Nn \keys_find_code_name: { + \keys_separate_path: + \keys_if_cmd_exist:nTF + { \c_keys_properties_path_tl / \l_keys_current_key_name_tl } { + \keys_use_cmd:n + {\c_keys_properties_path_tl / \l_keys_current_key_name_tl} + }{ + \keys_if_cmd_exist:nTF + { \l_keys_current_path_tl / unknown } { + \keys_use_cmd:n { \l_keys_current_path_tl / unknown } + }{ + \keys_error:n { unknown~key } + } + } +} +\prg_new_conditional:Nnn \keys_if_cmd_exist:n {TF,T,F} { + \if_cs_exist:w \c_keys_cs_prefix_tl #1 /._cmd:w \cs_end: + \prg_return_true: + \else: + \prg_return_false: + \fi: +} +\prg_new_conditional:Nnn \keys_if_exist:n {TF,T,F} { + \if_cs_exist:w \c_keys_cs_prefix_tl #1 \cs_end: + \prg_return_true: + \else: + \prg_return_false: + \fi: +} +\prg_new_conditional:Nnn \keys_if_value:n {TF,T,F} { + \if_cs_exist:w + \c_keys_cs_prefix_tl \l_keys_current_key_full_tl /._ #1 _bool + \cs_end: + \prg_return_true: + \else: + \prg_return_false: + \fi: +} +\cs_new:Nn \keys_no_value_elt:n { + \bool_set_true:N \l_keys_no_value_bool + \keys_process_elt:nn {#1} { } +} +\cs_new:Nn \keys_value_elt:nn { + \bool_set_false:N \l_keys_no_value_bool + \keys_process_elt:nn {#1} {#2} +} +\cs_new:Nn \keys_parse:n { \ERROR } +\cs_new:Nn \keys_parse_list:n { + \cs_set_eq:NN \KV_key_value_elt:nn \keys_value_elt:nn + \cs_set_eq:NN \KV_key_no_value_elt:n \keys_no_value_elt:n + \keys_parse:n {#1} +} +\cs_new_nopar:Nn \keys_path_add:N { + \exp_after:wN \keys_path_add:w #1 \q_stop +} +\cs_new_nopar:Npn \keys_path_add:w { + \exp_after:wN \peek_meaning:NTF \c_keys_root_tl { + \use_none_delimit_by_q_stop:w + }{ + \keys_path_add_aux:w + } +} +\cs_new_nopar:Npn \keys_path_add_aux:w #1 \q_stop { + \tl_set:Nx \l_keys_current_key_full_tl {\l_keys_default_path_tl #1} +} +\cs_new:Nn \keys_process_elt:nn { + \tl_set:Nx \l_keys_current_key_full_tl {#1} + \toks_set:Nn \l_keys_current_value_toks {#2} + \keys_path_add:N \l_keys_current_key_full_tl + \keys_default_add: + \keys_if_value:nTF { required } { + \bool_if:NTF \l_keys_no_value_bool { + \keys_error:n { value~required } + }{ + \keys_process_elt_aux: + } + }{ + \keys_process_elt_aux: + } +} +\cs_new:Nn \keys_process_elt_aux: { + \keys_if_value:nTF { forbidden } { + \bool_if:NTF \l_keys_no_value_bool { + \keys_find_code_full: + }{ + \keys_error:nn { value~forbidden } + { \toks_use:N \l_keys_current_value_toks } + } + }{ + \keys_find_code_full: + } +} +\cs_new_nopar:Nn \keys_separate_path: { + \tl_clear:N \l_keys_current_path_tl + \exp_after:wN \keys_separate_path:w \l_keys_current_key_full_tl + / \q_stop +} +\cs_new_nopar:Npn \keys_separate_path:w / #1 / #2 \q_stop { + \tl_if_empty:nTF {#2} { + \tl_set:Nn \l_keys_current_key_name_tl {#1} + }{ + \tl_put_right:Nn \l_keys_current_path_tl { / #1 } + \keys_separate_path:w /#2 \q_stop + } +} +\cs_new_nopar:Nn \keys_set:NN { + \keys_parse_list:n { + \c_keys_properties_path_tl /.code:n = { + #1 #2 {##1} + } + } +} +\cs_new_nopar:Nn \keys_set:Nnn { + \keys_parse_list:n { + \c_keys_properties_path_tl /.code:x = { + \exp_not:N #1 { #2 \l_keys_current_module_tl #3 } {##1} + } + } +} +\cs_new:Nn \keys_set_cmd:nn { + \keys_clear_properties:n {#1} + \cs_set:cpn { \c_keys_cs_prefix_tl #1 /._cmd:w } ##1 {#2} +} +\cs_new:Nn \keys_set_cmd:nx { + \keys_clear_properties:n {#1} + \cs_set:cpx { \c_keys_cs_prefix_tl #1 /._cmd:w } ##1 {#2} +} +\cs_new:Nn \keys_set_cmd:nNn { + \keys_clear_properties:n {#1} + \cs_generate_from_arg_count:cNnn { \c_keys_cs_prefix_tl #1 /._cmd:w } + \cs_set:Npn #2 {#3} + \keys_store:nn { #1 /._num_args_tl} {#2} +} +\cs_new:Nn \keys_set_cmd:nNx { + \keys_clear_properties:n {#1} + \cs_generate_from_arg_count:cNnn { \c_keys_cs_prefix_tl #1 /._cmd:w } + \cs_set:Npx #2 {#3} + \keys_store:nn { #1 /._num_args_tl} {#2} +} +\cs_new:Nn \keys_store:nn { + \tl_set:cn { \c_keys_cs_prefix_tl #1 } {#2} +} +\cs_new:Nn \keys_store:nx { + \tl_set:cx { \c_keys_cs_prefix_tl #1 } {#2} +} +\cs_new_nopar:Nn \keys_toks_set:Nn { + \exp_args:NNv \toks_set:Nn #1 { \c_keys_cs_prefix_tl #2 } +} +\cs_new_nopar:Nn \keys_try: { + \bool_set_false:N \l_keys_success_bool + \keys_if_cmd_exist:nT { \l_keys_current_path_tl } { + \bool_set_true:N \l_keys_success_bool + \bool_if:NT \l_keys_no_value_bool { + \keys_if_exist:nT + { \l_keys_current_path_tl /._default_tl } { + \keys_toks_set:Nn \l_keys_current_value_toks + { \l_keys_current_path_tl /._default_tl } + } + } + \cs_set_eq:NN \l_keys_current_key_full_tl \l_keys_current_path_tl + \keys_use_cmd:n { \l_keys_current_path_tl } + } +} +\cs_new_nopar:Nn \keys_undefine:n { + \cs_set_eq:cN { \c_keys_cs_prefix_tl #1 } \c_undefined +} +\cs_new_nopar:Nn \keys_use:n { + \use:c { \c_keys_cs_prefix_tl #1 } +} +\cs_new_nopar:Nn \keys_use_cmd:n { + \exp_args:Nno \keys_use_cmd:nn {#1} + { \toks_use:N \l_keys_current_value_toks } +} +\cs_new_nopar:Nn \keys_use_cmd:nn { + \keys_if_exist:nTF { #1 /._num_args_tl } { + \keys_use_cmd_aux:nn {#1} {#2} + }{ + \keys_use:n {#1/._cmd:w} {#2} + } +} +\cs_new_nopar:Nn \keys_use_cmd_aux:nn { + \tl_if_empty:nTF {#2} { + \cs_set:Npn \keys_use_cmd_aux:w { + \keys_use:n { #1 /._cmd:w } + } + \exp_after:wN \exp_after:wN \exp_after:wN \keys_use_cmd_aux:w + \cs:w + c_keys_ \keys_use:n { #1 /._num_args_tl } _empty_tl + \cs_end: + }{ + \keys_use:n { #1 /._cmd:w } #2 + } +} +\cs_new_nopar:Npn \keys_msg_new:nn #1 { + \msg_new:nnn { keys } {#1} +} +\cs_new_protected_nopar:Nn \keys_error:nn { + \msg_error:nnxx { keys } {#1} { \l_keys_current_key_full_tl } {#2} +} +\cs_new_protected_nopar:Nn \keys_error:n { + \msg_error:nnx { keys } {#1} { \l_keys_current_key_full_tl } +} +\keys_msg_new:nn + { unknown~key } + {The key `#1' is unknown and is being ignored.} +\keys_msg_new:nn + { value~required } + {The key `#1' requires a value\\% + and is being ignored.} +\keys_msg_new:nn + { value~forbidden } + {The key `#1' cannot taken a value:\\% + the given input `#2' is being ignored.} +\keys_msg_new:nn + { Boolean~expected } + {Key `#1' takes the Boolean values\\% + `true' and `false'~only.\\% + The given value `#2' is being ignored.} +\keys_msg_new:nn + { not_boolean } + {Key `#1' is not a Boolean key: you cannot create a complement.} +\keys_msg_new:nn + { unknown~choice } + {Choice `#2' unknown for key `#1':\\% + the key is being ignored.} +\keys_set_cmd:nn { \c_keys_properties_path_tl /.code:n } { + \keys_set_cmd:nn { \l_keys_current_path_tl } {#1} +} +\keys_set_cmd:nNn { \c_keys_properties_path_tl /.code:Nn } 2 { + \keys_set_cmd:nNn { \l_keys_current_path_tl } #1 {#2} +} +\keys_manage_quick:n { + \c_keys_errors_path_tl /unknown/.code:n = { + \keys_error:n { unknown~key } + } +} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.code:x/.code:n = { + \keys_set_cmd:nx { \l_keys_current_path_tl } {#1} + }, + \c_keys_properties_path_tl /.code:Nx/.code:Nn = 2 { + \keys_set_cmd:nNx { \l_keys_current_path_tl } {#1} {#2} + } +} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.cd:/.code:n = { + \tl_set:Nx \l_keys_default_path_tl { \l_keys_current_path_tl / } + } +} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.value_required:/.code:n = { + \keys_bool_new:n { \l_keys_current_path_tl /._required_bool } + \keys_undefine:n { \l_keys_current_path_tl /._forbidden_bool } + }, + \c_keys_properties_path_tl /.value_forbidden:/.code:n = { + \keys_bool_new:n { \l_keys_current_path_tl /._forbidden_bool } + \keys_undefine:n { \l_keys_current_path_tl /._required_bool } + } +} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.default:n/.code:n = { + \keys_store:nn { \l_keys_current_path_tl /._default_tl } {#1} + \keys_undefine:n { \l_keys_current_path_tl /._required_bool } + } +} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.tl_set:N/.code:n = { + \keys_check_exists:NN #1 \tl_new:N + \keys_set:NN \tl_set:Nn #1 + }, + \c_keys_properties_path_tl /.tl_set_x:N/.code:n = { + \keys_check_exists:NN #1 \tl_new:N + \keys_set:NN \tl_set:Nx #1 + }, + \c_keys_properties_path_tl /.tl_gset:N/.code:n = { + \keys_check_exists:NN #1 \tl_new:N + \keys_set:NN \tl_gset:Nn #1 + }, + \c_keys_properties_path_tl /.tl_gset_x:N/.code:n = { + \keys_check_exists:NN #1 \tl_new:N + \keys_set:NN \tl_gset:Nx #1 + } +} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.int_set:N/.code:n = { + \keys_check_exists:NN #1 \int_new:N + \keys_set:NN \int_set:Nn #1 + }, + \c_keys_properties_path_tl /.int_gset:N/.code:n = { + \keys_check_exists:NN #1 \int_new:N + \keys_set:NN \int_gset:Nn #1 + }, + \c_keys_properties_path_tl /.skip_set:N/.code:n = { + \keys_check_exists:NN #1 \skip_new:N + \keys_set:NN \skip_set:Nn #1 + }, + \c_keys_properties_path_tl /.skip_gset:N/.code:n = { + \keys_check_exists:NN #1 \skip_new:N + \keys_set:NN \skip_gset:Nn #1 + }, + \c_keys_properties_path_tl /.toks_set:N/.code:n = { + \keys_check_exists:NN #1 \toks_new:N + \keys_set:NN \toks_set:Nn #1 + }, + \c_keys_properties_path_tl /.toks_gset:N/.code:n = { + \keys_check_exists:NN #1 \toks_new:N + \keys_set:NN \toks_gset:Nn #1 + } +} +\keys_manage_quick:n { + \c_keys_utilities_path_tl /current_module:n/.code:n = { + \tl_if_empty:nTF {#1} { + \tl_clear:N \l_keys_current_module_tl + }{ + \tl_set:Nn \l_keys_current_module_tl { #1 _ } + } + } +} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.tl_set:n/.code:n = { + \keys_check_exists:cN { l_ #1 _tl } \tl_new:N + \keys_set:Nnn \tl_set:cn { l_ } { #1 _tl } + }, + \c_keys_properties_path_tl /.tl_set_x:n/.code:n = { + \keys_check_exists:cN { l_ #1 _tl } \tl_new:N + \keys_set:Nnn \tl_set:cx { l_ } { #1 _tl } + }, + \c_keys_properties_path_tl /.tl_gset:n/.code:n = { + \keys_check_exists:cN { g_ #1 _tl } \tl_new:N + \keys_set:Nnn \tl_gset:cn { g_ } { #1 _tl } + }, + \c_keys_properties_path_tl /.tl_gset_x:n/.code:n = { + \keys_check_exists:cN { g_ #1 _tl } \tl_new:N + \keys_set:Nnn \tl_gset:cx { g_ } { #1 _tl } + }, + \c_keys_properties_path_tl /.int_set:n/.code:n = { + \keys_check_exists:cN { l_ #1 _int } \int_new:N + \keys_set:Nnn \int_set:cn { l_ } { #1 _int } + }, + \c_keys_properties_path_tl /.int_gset:n/.code:n = { + \keys_check_exists:cN { g_ #1 _int } \int_new:N + \keys_set:Nnn \int_gset:cn { g_ } { #1 _int } + }, + \c_keys_properties_path_tl /.skip_set:n/.code:n = { + \keys_check_exists:cN { l_ #1 _skip } \skip_new:N + \keys_set:Nnn \skip_set:cn { l_ } { #1 _skip } + }, + \c_keys_properties_path_tl /.skip_gset:n/.code:n = { + \keys_check_exists:cN { g_ #1 _skip } \skip_new:N + \keys_set:Nnn \skip_gset:cn { g_ } { #1 _skip } + }, + \c_keys_properties_path_tl /.toks_set:n/.code:n = { + \keys_check_exists:cN { g_ #1 _toks } \toks_new:N + \keys_set:Nnn \toks_set:cn { l_ } { #1 _toks } + }, + \c_keys_properties_path_tl /.toks_gset:n/.code:n = { + \keys_check_exists:cN { g_ #1 _toks } \toks_new:N + \keys_set:Nnn \toks_gset:cn { g_ } { #1 _toks } + }, +} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.bool_set:N/.code:n = { + \keys_bool_set:nN { set } #1 + }, + \c_keys_properties_path_tl /.bool_gset:N/.code:n = { + \keys_bool_set:nN { gset } #1 + }, + \c_keys_properties_path_tl /.bool_set:n/.code:n = { + \keys_bool_set:nnn { set } { l_ } { #1 } + }, + \c_keys_properties_path_tl /.bool_gset:n/.code:n = { + \keys_bool_set:nnn { gset } { g_ } { #1 } + }, +} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.bool_set_inverse:N/.code:n = { + \keys_bool_set_inverse:nN { set } #1 + }, + \c_keys_properties_path_tl /.bool_gset_inverse:N/.code:n = { + \keys_bool_set_inverse:nN { gset } #1 + }, + \c_keys_properties_path_tl /.bool_set_inverse:n/.code:n = { + \keys_bool_set_inverse:nnn { set } { l_ } { #1 } + }, + \c_keys_properties_path_tl /.bool_gset_inverse:n/.code:n = { + \keys_bool_set_inverse:nnn { gset } { g_ } { #1 } + }, +} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.expects_choice:/.code:n = { + \keys_manage_internal:n { + \l_keys_current_path_tl /.cd:, + .code:n = { + \tl_set:Nn \l_keys_current_choice_tl {##1} + \int_zero:N \l_keys_current_choice_int + \exp_args:No \keys_parse_list:n + { \l_keys_current_key_full_tl / ##1 } + }, + unknown/.code:n = { + \keys_error:nn { unknown~choice } + { \l_keys_current_key_name_tl } + } + } + }, +} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.create_choices:nn/.code:Nn = 2 { + \keys_choices_create:Nnn n {#1} {#2} + }, + \c_keys_properties_path_tl /.create_choices:nx/.code:Nn = 2 { + \keys_choices_create:Nnn x {#1} {#2} + }, +} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.use_keys:n/.code:n = { + \keys_manage_internal:n { + \l_keys_current_path_tl /.code:n = { \keys_parse_list:n {#1} } + } + }, + \c_keys_properties_path_tl /.use_keys:x/.code:n = { + \keys_manage_internal:n { + \l_keys_current_path_tl /.code:x = { + \exp_not:N \keys_parse_list:n {#1} + } + } + }, + \c_keys_properties_path_tl /.use_keys:Nn/.code:Nn = 2 { + \keys_manage_internal:n { + \l_keys_current_path_tl /.code:Nn = #1 { \keys_parse_list:n {#2} } + } + }, + \c_keys_properties_path_tl /.use_keys:Nx/.code:Nn = 2 { + \keys_manage_internal:n { + \l_keys_current_path_tl /.code:Nx = + #1 { \exp_not:N \keys_parse_list:n {#2} } + } + } +} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.try:n/.code:n = { \keys_try: }, + \c_keys_properties_path_tl /.retry:n/.code:n = { + \bool_if:NF \l_keys_success_bool { \keys_try: } + } +} +\keys_manage_quick:n { + \c_keys_properties_path_tl /.show_code:/.code:n = { + \cs_show:c { + \c_keys_cs_prefix_tl \l_keys_current_path_tl /._cmd:w + } + }, + \c_keys_properties_path_tl /.show_key:/.code:n = { + \cs_show:c { \c_keys_cs_prefix_tl \l_keys_current_path_tl } + } +} +%% +%% Copyright (C) 2008-2009 by +%% Joseph Wright <joseph.wright@morningstar2.co.uk> +%% +%% 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 work is "maintained" (as per LPPL maintenance status) by +%% Joseph Wright. +%% +%% This work consists of the file keys3.dtx +%% and the derived files keys3.pdf, +%% keys3.sty and +%% keys3.ins. +%% +%% +%% End of file `keys3.sty'. diff --git a/Master/texmf-dist/tex/latex/keys3/keys3opts2.sty b/Master/texmf-dist/tex/latex/keys3/keys3opts2.sty new file mode 100644 index 00000000000..4a2cd7eb090 --- /dev/null +++ b/Master/texmf-dist/tex/latex/keys3/keys3opts2.sty @@ -0,0 +1,90 @@ +%% +%% This is file `keys3opts2.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% keys3opts2.dtx (with options: `package') +%% --------------------------------------------------------------- +%% The keys3opts2 package --- Using keys3 for LaTeX2e options +%% Maintained by Joseph Wright +%% E-mail: joseph.wright@morningstar2.co.uk +%% Released under the LaTeX Project Public License v1.3c or later +%% See http://www.latex-project.org/lppl.txt +%% --------------------------------------------------------------- +%% +%% EXPERIMENTAL CODE +%% +%% Do not distribute this file without also distributing the +%% source files specified above. +%% +%% Do not distribute a modified version of this file. +%% +\RequirePackage{l3names} +\GetIdInfo$Id: keys3opts2.dtx 93 2009-05-03 20:34:46Z josephwright $ + {Using keys3 for LaTeX2e options} +\ProvidesExplPackage + {\filename}{\filedate}{\fileversion}{\filedescription} +\RequirePackage{keys3} +\clist_new:N \l_keys_options_ltx_clist +\cs_new:Nn \keys_options_ltx:n { + \tl_set:Nx \l_keys_current_key_tl {#1} + \keys_path_add:N \l_keys_current_key_tl + \clist_clear:N \l_keys_options_ltx_clist + \cs_if_eq:NNTF \@currext \@clsextension { + \cs_if_free:cF { opt@ \@currname . \@currext } { + \clist_map_function:cN { opt@ \@currname . \@currext } + \keys_options_ltx_cls:n + } + }{ + \cs_if_free:NF \@classoptionslist { + \clist_map_function:NN \@classoptionslist \keys_options_ltx_pkg:n + } + \cs_if_free:cF { opt@ \@currname . \@currext } { + \exp_args:NNc \clist_concat:NNN \l_keys_options_ltx_clist + { opt@ \@currname . \@currext } \l_keys_options_ltx_clist + } + } + \clist_put_left:Nn \l_keys_options_ltx_clist { #1 /.cd: } + \exp_args:NV \keys_manage:n \l_keys_options_ltx_clist + \AtEndOfPackage { \cs_set_eq:NN \@unprocessedoptions \scan_stop: } +} +\cs_new:Nn \keys_options_ltx_cls:n { + \keys_if_cmd_exist:nTF { + \l_keys_current_key_tl / \keys_options_ltx_strip_eq:w #1 = \q_stop + }{ + \clist_put_right:Nn \l_keys_options_ltx_clist {#1} + }{ + \clist_put_right:Nn \@unusedoptionlist {#1} + } +} +\cs_new:Nn \keys_options_ltx_pkg:n { + \keys_if_cmd_really_exist:nT { + \l_keys_current_key_tl / \keys_options_ltx_strip_eq:w #1 = \q_stop + }{ + \clist_put_right:Nn \l_keys_options_ltx_clist {#1} + \clist_remove_element:Nn \@unusedoptionlist {#1} + } +} +\cs_new:Npn \keys_options_ltx_strip_eq:w #1 = #2 \q_stop {#1} +%% +%% Copyright (C) 2008-2009 by +%% Joseph Wright <joseph.wright@morningstar2.co.uk> +%% +%% 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 work is "maintained" (as per LPPL maintenance status) by +%% Joseph Wright. +%% +%% This work consists of the file keys3opts2.dtx +%% and the derived files keys3opts2.pdf, +%% keys3opts2.sty and +%% keys3opts2.ins. +%% +%% +%% End of file `keys3opts2.sty'. diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check index 811440d1332..a6390f71e8d 100755 --- a/Master/tlpkg/bin/tlpkg-ctan-check +++ b/Master/tlpkg/bin/tlpkg-ctan-check @@ -130,7 +130,8 @@ my @WorkingTLP = qw( iso10303 isodate isodoc isomath isonums isorot isotope itnumpar iwona jeopardy jknapltx jneurosci jpsj junicode jura juraabbrev jurabib juramisc jurarsp - kalender kastrup kerkis kerntest keystroke knuth koma-script kpfonts + kalender kastrup kerkis kerntest keys3 + keystroke knuth koma-script kpfonts l2picfaq l2tabu-english l2tabu-french l2tabu-it l2tabu-spanish labbook labelcas labels lastpage latex latex-doc-ptr latex2e-help-texinfo latex2man diff --git a/Master/tlpkg/tlpsrc/collection-latex3.tlpsrc b/Master/tlpkg/tlpsrc/collection-latex3.tlpsrc index 31ce4e920ab..642fea7d105 100644 --- a/Master/tlpkg/tlpsrc/collection-latex3.tlpsrc +++ b/Master/tlpkg/tlpsrc/collection-latex3.tlpsrc @@ -2,5 +2,6 @@ name collection-latex3 category Collection shortdesc LaTeX3 packages depend expl3 +depend keys3 depend xpackages depend collection-latex diff --git a/Master/tlpkg/tlpsrc/keys3.tlpsrc b/Master/tlpkg/tlpsrc/keys3.tlpsrc new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/Master/tlpkg/tlpsrc/keys3.tlpsrc |