[latex3-commits] [git/LaTeX3-latex3-latex2e] clsguide-cleanup: Document keyval option handling (c25d65f2)

Joseph Wright joseph.wright at morningstar2.co.uk
Fri Jan 13 08:43:11 CET 2023


Repository : https://github.com/latex3/latex2e
On branch  : clsguide-cleanup
Link       : https://github.com/latex3/latex2e/commit/c25d65f29dac5f2118ce866bd5b4524f6c26ac2b

>---------------------------------------------------------------

commit c25d65f29dac5f2118ce866bd5b4524f6c26ac2b
Author: Joseph Wright <joseph.wright at morningstar2.co.uk>
Date:   Fri Jan 13 07:43:11 2023 +0000

    Document keyval option handling
    
    This moves \DeclareOption, etc., to the deprecated
    part. The text itself is a straight copy from ltkeys.


>---------------------------------------------------------------

c25d65f29dac5f2118ce866bd5b4524f6c26ac2b
 base/doc/clsguide.tex | 496 +++++++++++++++++++++++++++++---------------------
 1 file changed, 290 insertions(+), 206 deletions(-)

diff --git a/base/doc/clsguide.tex b/base/doc/clsguide.tex
index 7b4e2f98..5ddb9cab 100644
--- a/base/doc/clsguide.tex
+++ b/base/doc/clsguide.tex
@@ -425,6 +425,16 @@ for example, the |twocolumn| option is declared by the |article| class. Note
 that the name of an option should contain only those characters allowed in a
 `\LaTeX{} name'; in particular it must not contain any control sequences.
 
+\LaTeX{} supports two methods for creating options: a key--value system and a
+`simple text` approach. The key--value system is recommended for new classes
+and packages, and is more flexible in handling of option classes than the
+simple text approach. Both option methods use the same basic structure within
+the \LaTeX{} source: declaration of options first then processing options in a
+second step. Both also allow options to be passed on to other packages or an
+underlying class. As the `classical' simple text approach is conceptually more
+straight-forward to illustrate, it is used here to show the general structure:
+see Section~\ref{Sec:opt:keyval} for full details of the key--value approach.
+
 An option is declared as follows:
 \begin{verbatim}
    \DeclareOption{<option>}{<code>}
@@ -697,67 +707,129 @@ The two |WithOptions| versions simply load the class (or package) file with
 exactly those options that are being used by the current file (class or
 package). See below, in \ref{Sec:opmove}, for further discussion of their use.
 
-\subsection{Option declaration}
-\label{Sec:commands.options.dec}
+\subsection{Delaying code}
+\label{Sec:delays}
 
-The following commands deal with the declaration and handling of options to
-document classes and packages. Every option name must be a `\LaTeX{} name'.
+As noted earlier, a sophisticated hook system is available and described in
+\texttt{lthooks}. Here, we document a small set of convenient short names for
+common hooks.
 
-There are some commands designed especially for use within the \m{code}
-argument of these commands (see below).
+These first two commands are also intended primarily for use within the
+\m{code} argument of |\DeclareOption| or |\DeclareOption*|.
 
 \begin{decl}
-  |\DeclareOption| \arg{option-name} \arg{code}
+  |\AtEndOfClass| \arg{code}\\
+  |\AtEndOfPackage| \arg{code}
 \end{decl}
-This makes \m{option-name} a `declared option' of the class or package in which
-it is put.
-
-The \m{code} argument contains the code to be executed if that option is
-specified for the class or package; it can contain any valid \LaTeXe{}
-construct.
+These commands declare \m{code} that is saved away internally and then executed
+after processing the whole of the current class or package file.
 
-Example:
-\begin{verbatim}
-   \DeclareOption{twoside}{\@twosidetrue}
-\end{verbatim}
+Repeated use of these commands is permitted: the code in the arguments is
+stored (and later executed) in the order of their declarations.
 
 \begin{decl}
-  |\DeclareOption*| \arg{code}
+  |\AtBeginDocument| \arg{code}\\
+  |\AtEndDocument| \arg{code}
 \end{decl}
-This declares the \m{code} to be executed for every option which is specified
-for, but otherwise not explicitly declared by, the class or package; this code
-is called the `default option code' and it can contain any valid \LaTeXe{}
-construct.
+These commands declare \m{code} to be saved internally and executed while
+\LaTeX{} is executing |\begin{document}| or |\end{document}|.
 
-If a class file contains no |\DeclareOption*| then, by default, all specified
-but undeclared options for that class will be silently passed to all packages
-(as will the specified and declared options for that class).
+The \m{code} specified in the argument to |\AtBeginDocument| is executed near
+the end of the |\begin{document}| code, \emph{after} the font selection tables
+have been set up. It is therefore a useful place to put code which needs to be
+executed after everything has been prepared for typesetting and when the normal
+font for the document is the current font.
 
-If a package file contains no |\DeclareOption*| then, by default, each
-specified but undeclared option for that package will produce an error.
+The |\AtBeginDocument| hook should not be used for code that does any
+typesetting since the typeset result would be unpredictable.
 
-\subsection{Commands within option code}
-\label{Sec:within.code}
+The \m{code} specified in the argument to |\AtEndDocument| is executed at the
+beginning of the |\end{document}| code, \emph{before} the final page is
+finished and before any leftover floating environments are processed. If some
+of the \m{code} is to be executed after these two processes, you should include
+a |\clearpage| at the appropriate point in \m{code}.
 
-These two commands can be used only within the \m{code} argument of either
-|\DeclareOption| or |\DeclareOption*|. Other commands commonly used within
-these arguments can be found in the next few subsections.
+Repeated use of these commands is permitted: the code in the arguments is
+stored (and later executed) in the order of their declarations.
+
+\subsection{Creating and using keyval options}
+\label{Sec:opt:keyval}
+
+As with any key--value input, using key--value pairs as package or class
+options has two parts: creating the key options and setting (using) them.
+Options created in this way \emph{may} be used after package loading as general
+key--value settings: this will depend on the nature of the underlying code.
 
 \begin{decl}
-  |\CurrentOption|
+  |\DeclareKeys| \oarg{family} \arg{declarations}
 \end{decl}
-This expands to the name of the current option.
+This command creates a series of options from a comma-separated
+\m{declarations} list. Each entry in this list is a key--value pair, with the
+\m{key} having one or more \m{properties}. A small number of `basic'
+\m{properties} are described below. The full range of properties, provided by
+\texttt{l3keys}, can also be used for more powerful processing. See
+\texttt{interface3} for the full details.
+   
+The basic properties provided here are
+\begin{itemize}
+  \item \texttt{.code} --- execute arbitrary code
+  \item \texttt{.if} --- sets a \TeX{} |\if...| switch
+  \item \texttt{.ifnot} --- sets an inverted \TeX{} |\if...| switch
+  \item \texttt{.store} --- stores a value in a macro
+  \item \texttt{.usage} -- defines whether the option can be given only
+    when loading (\texttt{load}), in the preamble (\texttt{preamble}) or
+    has no limitation on scope (\texttt{general})
+\end{itemize}
+The part of the \meta{key} before the \m{property} is the \m{name}, with the
+\m{value} working with the \m{property} to define the behaviour of the option.
+
+For example, with
+\begin{verbatim}
+\DeclareKeys[mypkg]
+ {
+   draft.if          = @mypkg at draft      ,
+   draft.usage       = preamble          ,
+   name.store        = \@mypkg at name      ,
+   name.usage        = load              ,
+   second-name.store = \@mypkg at other@name
+ }
+\end{verbatim}
+three options would be create. The option \texttt{draft} can be given anywhere
+in the preamble, and will set a switch called |\if at mypkg@draft|. The option
+\texttt{name} can only be given during package loading, and will save whatever
+value it is given in |\@mypkg at name|. Finally, the option \texttt{second-name}
+can be given anywhere, and will save its value in |\@mypkg at other@name|.
+
+Keys created \emph{before} the use of |\ProcessKeyOptions|act as package
+options.
 
 \begin{decl}
-  |\OptionNotUsed|
+  |\DeclareUnknownKeyHandler| \oarg{family} \arg{code}
 \end{decl}
-This causes the current option to be added to the list of `unused options'.
+The command |\DeclareUnknownKeyHandler| may be used to define the behavior when
+an undefined key is encountered. The \m{code} will receive the unknown key name
+as |#1| and the value as |#2|. These can then be processed as appropriate,
+e.g.~by forwarding to another package.
+
+\begin{decl}
+  |\ProcessKeyOptions| \oarg{family}
+\end{decl}
+The |\ProcessKeyOptions| function is used to check the current option list
+against the keys defined for \m{family}. Global (class) options and local
+(package) options are checked when this function is called in a package.
+
+\begin{decl}
+  |\SetKeys| \oarg{family} \arg{keyvals}
+\end{decl}
+Sets (applies) the explicit list of \m{keyvals} for the \m{family}: it the
+latter is not given, the value of |\@currname| used. This command may be used
+within a package to set options before or after using |\ProcessKeyOptions|.
 
 \subsection{Passing options around}
 \label{Sec:opmove}
 
 These two commands are also very useful within the \m{code} argument of
-|\DeclareOption| or |\DeclareOption*|:
+options.
 \begin{decl}
   |\PassOptionsToPackage| \arg{options-list} \arg{package-name}\\
   |\PassOptionsToClass| \arg{options-list} \arg{class-name}
@@ -826,171 +898,6 @@ contrast, in the second example it will never be called with option
 the default option handler, but this handler is not used for |landscape|
 because that option is explicitly declared.
 
-\subsection{Delaying code}
-\label{Sec:delays}
-
-As noted earlier, a sophisticated hook system is available and described in
-\texttt{lthooks}. Here, we document a small set of convenient short names for
-common hooks.
-
-These first two commands are also intended primarily for use within the
-\m{code} argument of |\DeclareOption| or |\DeclareOption*|.
-
-\begin{decl}
-  |\AtEndOfClass| \arg{code}\\
-  |\AtEndOfPackage| \arg{code}
-\end{decl}
-These commands declare \m{code} that is saved away internally and then executed
-after processing the whole of the current class or package file.
-
-Repeated use of these commands is permitted: the code in the arguments is
-stored (and later executed) in the order of their declarations.
-
-\begin{decl}
-  |\AtBeginDocument| \arg{code}\\
-  |\AtEndDocument| \arg{code}
-\end{decl}
-These commands declare \m{code} to be saved internally and executed while
-\LaTeX{} is executing |\begin{document}| or |\end{document}|.
-
-The \m{code} specified in the argument to |\AtBeginDocument| is executed near
-the end of the |\begin{document}| code, \emph{after} the font selection tables
-have been set up. It is therefore a useful place to put code which needs to be
-executed after everything has been prepared for typesetting and when the normal
-font for the document is the current font.
-
-The |\AtBeginDocument| hook should not be used for code that does any
-typesetting since the typeset result would be unpredictable.
-
-The \m{code} specified in the argument to |\AtEndDocument| is executed at the
-beginning of the |\end{document}| code, \emph{before} the final page is
-finished and before any leftover floating environments are processed. If some
-of the \m{code} is to be executed after these two processes, you should include
-a |\clearpage| at the appropriate point in \m{code}.
-
-Repeated use of these commands is permitted: the code in the arguments is
-stored (and later executed) in the order of their declarations.
-
-\subsection{Option processing}
-\label{Sec:commands.options}
-
-\begin{decl}
-  |\ProcessOptions|
-\end{decl}
-This command executes the \m{code} for each selected option.
-
-We shall first describe how |\ProcessOptions| works in a package file, and then
-how this differs in a class file.
-
-To understand in detail what |\ProcessOptions| does in a package file, you have
-to know the difference between \emph{local} and \emph{global} options.
-\begin{itemize}
-\item \textbf{Local options} are those which have been explicitly
-  specified for this particular package in the \m{options} argument of
-  any of these:
-\begin{quote}
-    |\PassOptionsToPackage{<options>}| \ |\usepackage[<options>]|\\
-    |\RequirePackage[<options>]|
-\end{quote}
-\item \textbf{Global options} are any other options that are specified
-  by the author in the \m{options} argument of
-    |\documentclass[<options>]|.
-\end{itemize}
-For example, suppose that a document begins:
-\begin{verbatim}
-   \documentclass[german,twocolumn]{article}
-   \usepackage{gerhardt}
-\end{verbatim}
-whilst package |gerhardt| calls package |fred| with:
-\begin{verbatim}
-   \PassOptionsToPackage{german,dvips,a4paper}{fred}
-   \RequirePackage[errorshow]{fred}
-\end{verbatim}
-then:
-\begin{itemize}
-\item |fred|'s local options are |german|, |dvips|, |a4paper|
-  and |errorshow|;
-\item |fred|'s only global option is |twocolumn|.
-\end{itemize}
-
-When |\ProcessOptions| is called, the following happen.
-\begin{itemize}
-\item \emph{First}, for each option so far declared in |fred.sty|
-  by |\DeclareOption|, it looks to see if that option is either a
-  global or a local option for |fred|: if it is then the corresponding
-  code is executed.
-
-  This is done in the order in which these options
-  were declared in |fred.sty|.
-\item \emph{Then}, for each remaining \emph{local} option, the command
-  |\ds@<option>| is executed if it has been defined somewhere (other
-  than by a |\DeclareOption|); otherwise, the `default option code' is
-  executed.  If no default option code has been declared then an error
-  message is produced.
-
-  This is done in the order in which these
-  options were specified.
-\end{itemize}
-Throughout this process, the system ensures that the code declared for
-an option is executed at most once.
-
-Returning to the example, if |fred.sty| contains:
-\begin{verbatim}
-   \DeclareOption{dvips}{\typeout{DVIPS}}
-   \DeclareOption{german}{\typeout{GERMAN}}
-   \DeclareOption{french}{\typeout{FRENCH}}
-   \DeclareOption*{\PackageWarning{fred}{Unknown `\CurrentOption'}}
-   \ProcessOptions\relax
-\end{verbatim}
-then the result of processing this document will be:
-\begin{verbatim}
-   DVIPS
-   GERMAN
-   Package fred Warning: Unknown `a4paper'.
-   Package fred Warning: Unknown `errorshow'.
-\end{verbatim}
-Note the following:
-
-\begin{itemize}
-\item the code for the |dvips| option is executed before that for the
-  |german| option, because that is the order in which they are declared
-  in |fred.sty|;
-\item the code for the |german| option is executed only once, when the
-  declared options are being processed;
-\item the |a4paper| and |errorshow| options produce the warning from
-  the code declared by |\DeclareOption*| (in the order in which they
-  were specified), whilst the |twocolumn| option does not: this is
-  because |twocolumn| is a global option.
-\end{itemize}
-
-In a class file, |\ProcessOptions| works in the same way, except that:
-\emph{all} options are local; and the default value for |\DeclareOption*| is
-|\OptionNotUsed| rather than an error.
-
-Note that, because |\ProcessOptions| has a |*|-form, it is wise to follow the
-non-star form with |\relax|, as in the previous examples, since this prevents
-unnecessary look ahead and possibly misleading error messages being issued.
-
-\begin{decl}
-  |\ProcessOptions*|
-\end{decl}
-This is like |\ProcessOptions| but it executes the options in the order
-specified in the calling commands, rather than in the order of declaration in
-the class or package. For a package this means that the global options are
-processed first.
-
-\begin{decl}
-  |\ExecuteOptions| \arg{options-list}
-\end{decl}
-
-It can be used to provide a `default option list' just before
-|\ProcessOptions|. For example, suppose that in a class file you want to set up
-the default design to be: two-sided printing; 11pt fonts; in two columns. Then
-it could specify:
-\begin{verbatim}
-   \ExecuteOptions{11pt,twoside,twocolumn}
-\end{verbatim}
-
 \subsection{Safe file commands}
 
 These commands deal with file input; they ensure that the non-existence of a
@@ -1106,11 +1013,11 @@ being used. This should be actual paper size, unlike |\textwidth| and
 \end{decl}
 
 As described in \texttt{usrguide}, case changing for text should be carried out
-using the commands \cs{MakeUppercase}, \cs{MakeLowercase} and
-\cs{MakeTitlecase}. If you need to change the cae of programmatic material, the
+using the commands |\MakeUppercase|, |\MakeLowercase| and
+|\MakeTitlecase|. If you need to change the cae of programmatic material, the
 team strongly suggest using the L3 programming layer commands in the
 \texttt{str} module. If you do not wish to do this, you should use the \TeX{}
-\cs{uppercase} and \cs{lowercase} primitives \emph{in this situation only}.
+|\uppercase| and |\lowercase| primitives \emph{in this situation only}.
 
 \subsection{Better user-defined math display environments}
 
@@ -1132,7 +1039,7 @@ does not work perfectly when used in the middle of a paragraph because an
 inter-word space appears at the beginning of the first line after the
 environment.
 
-You can to avoid this problem using \cs{ignorespacesafterend}; it should be
+You can to avoid this problem using |\ignorespacesafterend|; it should be
 inserted as shown here:
 \begin{verbatim}
   \newenvironment{texteqn}
@@ -1225,4 +1132,181 @@ This command is useful for checking the state of the system before your package
 starts altering the definitions of commands. It allows you to check, in
 particular, that no other package has redefined the same command.
 
+\subsection{Option declaration}
+\label{Sec:commands.options.dec}
+
+The following commands deal with the declaration and handling of options to
+document classes and packages using a classical `simple text' approach. Every
+option name must be a `\LaTeX{} name'.
+
+There are some commands designed especially for use within the \m{code}
+argument of these commands (see below).
+
+\begin{decl}
+  |\DeclareOption| \arg{option-name} \arg{code}
+\end{decl}
+This makes \m{option-name} a `declared option' of the class or package in which
+it is put.
+
+The \m{code} argument contains the code to be executed if that option is
+specified for the class or package; it can contain any valid \LaTeXe{}
+construct.
+
+Example:
+\begin{verbatim}
+   \DeclareOption{twoside}{\@twosidetrue}
+\end{verbatim}
+
+\begin{decl}
+  |\DeclareOption*| \arg{code}
+\end{decl}
+This declares the \m{code} to be executed for every option which is specified
+for, but otherwise not explicitly declared by, the class or package; this code
+is called the `default option code' and it can contain any valid \LaTeXe{}
+construct.
+
+If a class file contains no |\DeclareOption*| then, by default, all specified
+but undeclared options for that class will be silently passed to all packages
+(as will the specified and declared options for that class).
+
+If a package file contains no |\DeclareOption*| then, by default, each
+specified but undeclared option for that package will produce an error.
+
+\subsection{Commands within option code}
+\label{Sec:within.code}
+
+These two commands can be used only within the \m{code} argument of either
+|\DeclareOption| or |\DeclareOption*|. Other commands commonly used within
+these arguments can be found in the next few subsections.
+
+\begin{decl}
+  |\CurrentOption|
+\end{decl}
+This expands to the name of the current option.
+
+\begin{decl}
+  |\OptionNotUsed|
+\end{decl}
+This causes the current option to be added to the list of `unused options'.
+
+\subsection{Option processing}
+\label{Sec:commands.options}
+
+\begin{decl}
+  |\ProcessOptions|
+\end{decl}
+This command executes the \m{code} for each selected option.
+
+We shall first describe how |\ProcessOptions| works in a package file, and then
+how this differs in a class file.
+
+To understand in detail what |\ProcessOptions| does in a package file, you have
+to know the difference between \emph{local} and \emph{global} options.
+\begin{itemize}
+\item \textbf{Local options} are those which have been explicitly
+  specified for this particular package in the \m{options} argument of
+  any of these:
+\begin{quote}
+    |\PassOptionsToPackage{<options>}| \ |\usepackage[<options>]|\\
+    |\RequirePackage[<options>]|
+\end{quote}
+\item \textbf{Global options} are any other options that are specified
+  by the author in the \m{options} argument of
+    |\documentclass[<options>]|.
+\end{itemize}
+For example, suppose that a document begins:
+\begin{verbatim}
+   \documentclass[german,twocolumn]{article}
+   \usepackage{gerhardt}
+\end{verbatim}
+whilst package |gerhardt| calls package |fred| with:
+\begin{verbatim}
+   \PassOptionsToPackage{german,dvips,a4paper}{fred}
+   \RequirePackage[errorshow]{fred}
+\end{verbatim}
+then:
+\begin{itemize}
+\item |fred|'s local options are |german|, |dvips|, |a4paper|
+  and |errorshow|;
+\item |fred|'s only global option is |twocolumn|.
+\end{itemize}
+
+When |\ProcessOptions| is called, the following happen.
+\begin{itemize}
+\item \emph{First}, for each option so far declared in |fred.sty|
+  by |\DeclareOption|, it looks to see if that option is either a
+  global or a local option for |fred|: if it is then the corresponding
+  code is executed.
+
+  This is done in the order in which these options
+  were declared in |fred.sty|.
+\item \emph{Then}, for each remaining \emph{local} option, the command
+  |\ds@<option>| is executed if it has been defined somewhere (other
+  than by a |\DeclareOption|); otherwise, the `default option code' is
+  executed.  If no default option code has been declared then an error
+  message is produced.
+
+  This is done in the order in which these
+  options were specified.
+\end{itemize}
+Throughout this process, the system ensures that the code declared for
+an option is executed at most once.
+
+Returning to the example, if |fred.sty| contains:
+\begin{verbatim}
+   \DeclareOption{dvips}{\typeout{DVIPS}}
+   \DeclareOption{german}{\typeout{GERMAN}}
+   \DeclareOption{french}{\typeout{FRENCH}}
+   \DeclareOption*{\PackageWarning{fred}{Unknown `\CurrentOption'}}
+   \ProcessOptions\relax
+\end{verbatim}
+then the result of processing this document will be:
+\begin{verbatim}
+   DVIPS
+   GERMAN
+   Package fred Warning: Unknown `a4paper'.
+   Package fred Warning: Unknown `errorshow'.
+\end{verbatim}
+Note the following:
+
+\begin{itemize}
+\item the code for the |dvips| option is executed before that for the
+  |german| option, because that is the order in which they are declared
+  in |fred.sty|;
+\item the code for the |german| option is executed only once, when the
+  declared options are being processed;
+\item the |a4paper| and |errorshow| options produce the warning from
+  the code declared by |\DeclareOption*| (in the order in which they
+  were specified), whilst the |twocolumn| option does not: this is
+  because |twocolumn| is a global option.
+\end{itemize}
+
+In a class file, |\ProcessOptions| works in the same way, except that:
+\emph{all} options are local; and the default value for |\DeclareOption*| is
+|\OptionNotUsed| rather than an error.
+
+Note that, because |\ProcessOptions| has a |*|-form, it is wise to follow the
+non-star form with |\relax|, as in the previous examples, since this prevents
+unnecessary look ahead and possibly misleading error messages being issued.
+
+\begin{decl}
+  |\ProcessOptions*|
+\end{decl}
+This is like |\ProcessOptions| but it executes the options in the order
+specified in the calling commands, rather than in the order of declaration in
+the class or package. For a package this means that the global options are
+processed first.
+
+\begin{decl}
+  |\ExecuteOptions| \arg{options-list}
+\end{decl}
+
+It can be used to provide a `default option list' just before
+|\ProcessOptions|. For example, suppose that in a class file you want to set up
+the default design to be: two-sided printing; 11pt fonts; in two columns. Then
+it could specify:
+\begin{verbatim}
+   \ExecuteOptions{11pt,twoside,twocolumn}
+\end{verbatim}
+
 \end{document}





More information about the latex3-commits mailing list.