From 7b90a8aacceb4fdb1bfd9d67a541880603099624 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Fri, 12 Aug 2011 22:57:30 +0000 Subject: catoptions (12aug11) git-svn-id: svn://tug.org/texlive/trunk@23517 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/doc/latex/catoptions/README | 22 +- .../doc/latex/catoptions/catoptions-guide.pdf | Bin 0 -> 447426 bytes .../doc/latex/catoptions/catoptions-guide.tex | 314 +++++++++++++++++---- 3 files changed, 280 insertions(+), 56 deletions(-) create mode 100644 Master/texmf-dist/doc/latex/catoptions/catoptions-guide.pdf (limited to 'Master/texmf-dist/doc') diff --git a/Master/texmf-dist/doc/latex/catoptions/README b/Master/texmf-dist/doc/latex/catoptions/README index e336e3b278e..277392c5dce 100644 --- a/Master/texmf-dist/doc/latex/catoptions/README +++ b/Master/texmf-dist/doc/latex/catoptions/README @@ -1,6 +1,7 @@ This is the README file for the 'catoptions' package. SUMMARY + The 'catoptions' package changes package loading internals so that all subsequently loaded packages can rely on normal/standard catcodes of all ASCII characters. The package defines canonical @@ -8,14 +9,33 @@ control sequences to represent all the visible ASCII characters. It also provides robust options parsing mechanisms, in addition to many TeX programming tools. +LICENSE + +The 'catoptions' package may be distributed and/or modified under +the conditions of the LaTeX Project Public License, either +version 1.3 of this license or any later version. The latest +version of this license is in http://www.latex-project.org/lppl.txt +and version 1.3 or later is part of all distributions of LaTeX +version 2005/12/01 or later. + +The LPPL maintenance status of this software is 'author-maintained'. + +This software is provided 'as it is', without warranty of any kind, +either expressed or implied, including, but not limited to, the +implied warranties of merchantability and fitness for a particular +purpose. + AUTHOR + Ahmed Musa RELATED PACKAGES + The catcode section of the 'catoptions' package is based on the 'pcatcode' package by Michael J. Downes and David M. Jones. VERSION -Version 0.2.4, July 2011 + +Version 0.2.5, July 2011 diff --git a/Master/texmf-dist/doc/latex/catoptions/catoptions-guide.pdf b/Master/texmf-dist/doc/latex/catoptions/catoptions-guide.pdf new file mode 100644 index 00000000000..0952cd13491 Binary files /dev/null and b/Master/texmf-dist/doc/latex/catoptions/catoptions-guide.pdf differ diff --git a/Master/texmf-dist/doc/latex/catoptions/catoptions-guide.tex b/Master/texmf-dist/doc/latex/catoptions/catoptions-guide.tex index c9cb4ff5b67..41002076fdb 100644 --- a/Master/texmf-dist/doc/latex/catoptions/catoptions-guide.tex +++ b/Master/texmf-dist/doc/latex/catoptions/catoptions-guide.tex @@ -1,4 +1,3 @@ -\RequirePackage[usepox,kernelifnextchar]{catoptions} \documentclass[ use-a4-paper, use-10pt-font, @@ -20,10 +19,14 @@ \begin{document} \begin{frontmatter} -\title{The \texttt{\color{blue}catoptions} Package\titleref{t1}} -\titlenote[t1]{The package is available at - \iftogTF{pdf}{\url{\@titleurl}}{\url{\@shorttitleurl}}.} -\version{0.2.4} +\title{The \texttt{\color{blue}catoptions} Package\titleref{t1,t2}} +\titlenotes[t1,t2]{% + The package is available at \iftogTF{pdf}{\url{\@titleurl}} + {\url{\@shorttitleurl}}.\sep + This manual doesn't, as yet, explain all the currently available features and commands of + the \pkg'{catoptions}. This manual continues to evolve, but many of the available functions will appear in the user guide of the forthcoming \pkg'{ltxtools}. +} +\version{0.2.5} \titleurl{http://www.ctan.org/tex-archive/macros/latex/contrib/catoptions/} \shorttitleurl{http://www.ctan.org/} \author{Ahmed Musa \Email{amusa22@gmail.com}\\Preston, Lancashire, UK} @@ -31,14 +34,15 @@ \def\abstractname{\textsf{Summary}} \begin{abstract} \small - The \pkg'{catoptions} provides several extensions to the \pkgm'{pcatcode}. Apart from the tools related to setting up, preserving and restoring category codes, it includes many \texorlatex programming tools and even new list and options processing interfaces. It modifies the \latex kernel's options parsing mechanism to forestall premature expansion of options and values (in the manner of the \pkgs'{xkvltxp,kvoptions-patch}), so that the \pkg'{catoptions} may be loaded even before \hx{\documentclass}. In fact, the package is meant to be loaded on top of other packages, so as to exploit its catcode preserving scheme. Among other reasons, this necessitated the development of the options parsing scheme of this package. Only the catcode and options parsing facilities are treated in this manual; the application programming interfaces will be covered in the documentation of the \pkg'{ltxtools}. The machinery of the \pkg'{catoptions} adds no cost to the simple syntax of \LaTeX's native options parser. Users who are already familiar with \LaTeX's legacy options processing don't necessarily have to invest the time that is essential in learning the extensive machinery of existing key-value and option parsers. Existing packages don't have to be modified to use the features of the \pkg'{catoptions}. The \pkg'{catoptions}, while maintaining simplicity, does not strip off even one level of outer braces in parsing package options and in list processing. It robustly normalizes key-values and options prior to parsing. The options parsing scheme of the \pkg'{catoptions} has been tried as a replacement parser on the \pkgg{article} class and on many packages, including \pkgs'{hyperref, cleveref, natbib} without difficulties. Packages that redefine \latex's native options processing internals may not work properly with \pkg'{catoptions}. I know that \pkg'{xcolor} redefines \hx{\@declareoption} and the \pkg'{catoptions} has taken that fact into account, but there may be other packages that modify \latex's options processing internals that I am not aware of. + The \pkg'{catoptions} provides several extensions to the \pkgm'{pcatcode}. Apart from the tools related to setting up, preserving and restoring category codes, it includes many \texorlatex programming tools and even new list and options processing interfaces. It modifies the \latex kernel's options parsing mechanism to forestall premature expansion of options and values (in the manner of the \pkg'{xkvltxp,kvoptions-patch}), so that the \pkg'{catoptions} may be loaded even before \hx{\documentclass}. In fact, the package is meant to be loaded on top of other packages, so as to exploit its catcode preserving scheme. Among other reasons, this necessitated the development of the options parsing scheme of this package. Only the catcode and options parsing facilities are treated in this manual; the application programming interfaces will be covered in the documentation of the \pkg'{ltxtools}. The machinery of the \pkg'{catoptions} adds no cost to the simple syntax of \LaTeX's native options parser. Users who are already familiar with \LaTeX's legacy options processing don't necessarily have to invest the time that is essential in learning the extensive machinery of existing key-value and option parsers. Existing packages don't have to be modified to use the features of the \pkg'{catoptions}. The \pkg'{catoptions}, while maintaining simplicity, does not strip off even one level of outer braces in parsing package options and in list processing. It robustly normalizes key-values and options prior to parsing. The options parsing scheme of the \pkg'{catoptions} has been tried as a replacement parser on the \pkgg{article} class and on many packages, including \pkg'{hyperref, cleveref, natbib} without difficulties. Packages that redefine \latex's native options processing internals may not work properly with \pkg'{catoptions}. I know that \pkg'{xcolor} redefines \hx{\@declareoption} and the \pkg'{catoptions} has taken that fact into account, but there may be other packages that modify \latex's options processing internals that I am not aware of. \end{abstract} \let\licensename\relax \begin{license} -\xwmcolorbox[textalign=justified,outerframecolor=blue,innerframecolor=orange,width=.985\hsize]{% + \small +\xwmcolorbox[textalign=justified, outerframecolor=blue, innerframecolor=orange, + width=.985\hsize]{% This work (\ie, all the files in the \pkg'{catoptions} bundle) may be distributed and/or modified under the conditions of the \lppl, either version~1.3 of this license or any later version. - \endgraff The \lppl maintenance status of this software is _{author-maintained}. This software is provided _{as it is}, without warranty of any kind, either expressed or implied, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose. \endgraf \centerline{\makered{\CopyrightYear}}\vspace{-.8\baselineskip}\relax @@ -58,7 +62,7 @@ \docsection(sec:pkg-options){Package options} -\lletter{T}{he} \pkg'{catoptions} has the options shown in \autoref{tab:pkgoptions}. The boolean option \fxim{verbose} instructs the package to enter information onto the log file when some events happen (\eg, when commands are redefined by means of, say, the command \fx{\robust@redef}, which has the same syntax with \tex's legacy \hx{\def}; and when an option from the same family is multiply submitted to, say, \fx{\XExecuteOptions}). This option may be used in the future to provide debugging features for the package. +\lletter{T}{he} \pkg'{catoptions} has the options shown in \amref{tab:pkgoptions}. The boolean option \fxim{verbose} instructs the package to enter information onto the log file when some events happen (\eg, when commands are redefined by means of, say, the command \fx{\robust@redef}, which has the same syntax with \tex's legacy \hx{\def}; and when an option from the same family is multiply submitted to, say, \fx{\XExecuteOptions}). This option may be used in the future to provide debugging features for the package. \extrarowheight=2pt \arrayrulecolor{yellow} @@ -77,10 +81,10 @@ \endlastfoot \fx{verbose} & \hx{false} & The global boolean switch that determines if information should be logged for some tasks in the package.\\\hline \fx{usepox} & \hx{true} & The boolean switch that determines if the options parser of \pkgg{catoptions} should be used for all options processing of packages loaded after \hx{\documentclass} even if those packages are based on \usecsn{latex2e}'s native options processing scheme.\\\hline -\fx{kernelifnextchar} & \hx{true} & The boolean option that determines if the package uses \fxim{\ifnextcharTF} or \hx{\kernel@ifnextchar}; the former is based on an idea of Donald Arseneau, which allows even active characters to appear \quoted{as the next character}, but it is costlier than the latter.\\\hline +\fx{kernelifnextchar} & \hx{true} & The boolean option that determines if the package uses \fxim{\ifnextcharTF} or \hxi{\kernel@ifnextchar}; the former is based on an idea of Donald Arseneau, which allows even active characters to appear \quoted{as the next character}, but it is costlier than the latter.\\\hline \end{tabularx} -If the \pkg'{catoptions} is loaded before \hx{documentclass}, it will invariably use the options processing mechanism of the package (namely, the more robust commands \ffx'{\XDeclareOption, \XExecuteOptions, \XProcessOptions} in place of \latex's native commands \hhx'{\DeclareOption, \ExecuteOptions, \ProcessOptions})\footnote{The user interfaces of \ffx'{\XDeclareOption, \XExecuteOptions, \XProcessOptions} are similar to those of \hhx'{\DeclareOption, \ExecuteOptions, \ProcessOptions} but they aren't the same. See \autoref{sec:options-parse}.}. In that case, the legacy commands \hhx'{\DeclareOption, \ExecuteOptions, \ProcessOptions} are aliased to \ffx'{\XDeclareOption, \XExecuteOptions, \XProcessOptions}, respectively. The latter set of commands do immediately recognize that they have to deal with option functions that are based on the kernel's semantics. This allows expandable options and option values (together with options with spaces in their names) to be passed via \hx{\documentclass}---if \pkg{catoptions} is loaded before \hx{\documentclass}. This also implies that existing packages can use the options parsing scheme of \pkg'{catoptions} without modifying the packages. +If the \pkg'{catoptions} is loaded before \hx{documentclass}, it will invariably use the options processing mechanism of the package (namely, the more robust commands \ffx'{\XDeclareOption, \XExecuteOptions, \XProcessOptions} in place of \latex's native commands \hhx'{\DeclareOption, \ExecuteOptions, \ProcessOptions})\footnote{The user interfaces of \ffx'{\XDeclareOption, \XExecuteOptions, \XProcessOptions} are similar to those of \hhx'{\DeclareOption, \ExecuteOptions, \ProcessOptions} but they aren't the same. See \amref{sec:options-parse}.}. In that case, the legacy commands \hhx'{\DeclareOption, \ExecuteOptions, \ProcessOptions} are aliased to \ffx'{\XDeclareOption, \XExecuteOptions, \XProcessOptions}, respectively. The latter set of commands do immediately recognize that they have to deal with option functions that are based on the kernel's semantics. This allows expandable options and option values (together with options with spaces in their names) to be passed via \hx{\documentclass}---if \pkg{catoptions} is loaded before \hx{\documentclass}. This also implies that existing packages can use the options parsing scheme of \pkg'{catoptions} without modifying the packages. The option \fxim{usepox} directs the package to use the \pkg{catoptions}'s options processing scheme for all the packages loaded after \hx{\documentclass}, instead of \latex's native options parsing procedures. This allows \pkg{catoptions}'s options parsing scheme to be used for existing packages loaded after \hx{\documentclass} without modifying the packages. @@ -119,7 +123,7 @@ After issuing the command \fx{\GetCurrentCatcodeSubset}, you can do \finish{example} \fxim*{\currentcatcodesubset} -to see the current catcode setup. The command \fx{\cptfutureletsetup} is described in \autoref{sec:future-letting}. +to see the current catcode setup. The command \fx{\cptfutureletsetup} is described in \amref{sec:future-letting}. \start{example}[\UseNormalCatcodes] \ProvidesPackage{mypackage}[2011/01/16 v0.01] @@ -315,9 +319,11 @@ If the \ang{handler} contains the special literal form \fx{define/.code=} as in \finish{example} \fxim*{define/.code} -then each unknown option in families \ang{fams} will be momentarily defined and executed with the option function \ang{callback}. The family of the new option will be \fx{\cpt@currfam} (the prevailing family name); its default value will be \fx{\cpt@currval} (the value specified by the user for the unknown option); and its macro function will be the above-indicated \ang{callback}. Again, you can use \fx{#1}, \fx{#2} and \fx{#3} in \ang{handler} to refer to the current option family, option name, and option value, respectively. \xnote Functions \ang{fn1} and \ang{fn2} on \macref{mac:handler} will be executed for each unknown function in families \ang{fams}, but (unlike \ang{callback}) will not be used in defining unknown options of \ang{fams}. +then each unknown option in families \ang{fams} will be momentarily defined and executed with the option function \ang{callback}. The family of the new option will be \fx{\cpt@currfam} (the prevailing family name); its default value will be \fx{\cpt@currval} (the value specified by the user for the unknown option); and its macro function will be the above-indicated \ang{callback}. Again, you can use \fx{#1}, \fx{#2} and \fx{#3} in \ang{handler} to refer to the current option family, option name, and option value, respectively. -If the value given for the unknown option is \hx{true} or \hx{false}, the new (\ie, undeclared) option will be defined as a boolean option with macro prefix \quotedfx{\@currname @}; otherwise it will be defined as a command option with macro prefix \quotedfx{cmd\@currname @}. (See the descriptions of the commands \ffx'{\XDeclareCommandOption,\XDeclareBooleanOption} for the meaning of \quoted{macro prefix}.) It should be noted that the token \quoted{define} in the above syntax is not escaped, and that the token \fx{/.end} is mandatory. If \ang{callback} contains these literal forms, they have to be enclosed in curly braces. +\Note Functions \ang{fn1} and \ang{fn2} on \amref{mac:handler} will be executed for each unknown function in families \ang{fams}, but (unlike \ang{callback}) will not be used in defining unknown options of \ang{fams}. + +If the value given for the unknown option is \hx{true} or \hx{false}, the new (\ie, undeclared) option will be defined as a boolean option with macro prefix \quotedFx{\@currname @}; otherwise it will be defined as a command option with macro prefix \quotedfx{cmd\@currname @}. (See the descriptions of the commands \ffx'{\XDeclareCommandOption,\XDeclareBooleanOption} for the meaning of \quoted{macro prefix}.) It should be noted that the token \quoted{define} in the above syntax is not escaped, and that the token \fx{/.end} is mandatory. If \ang{callback} contains these literal forms, they have to be enclosed in curly braces. The following example, among other things, produces a warning when the user supplies an option that was not previously declared: @@ -346,7 +352,7 @@ And the following example passes undeclared options to \hx{article} class: \XDeclareOption|*{\PassOptionsToClass{#2=#3}{article}} \finish{example} -The following example instructs \fx{\XProcessOptions} to define all unknown keys on the fly with the call-back shown. +The following example instructs \fx{\XProcessOptions} to define all unknown keys on the fly with the callback shown. \start{example}[\XUnknownOptionHandler] \XUnknownOptionHandler{% @@ -372,7 +378,7 @@ If no default family handler has been provided by the user (through the macro \x where \ang{opts} are the comma-separated option names to be added to, or removed from, the list. -\Note Unknown options that appear in \fx{\XExternalOptions} list will not have their \ang{fn1}, \ang{fn2} and \ang{callback} of the default family handler (see \macref{mac:handler}) executed unless they contain one of the commands \hhx'{\PassOptionsToClass, \PassOptionsToPackage}. +\Note Unknown options that appear in \fx{\XExternalOptions} list will not have their \ang{fn1}, \ang{fn2} and \ang{callback} of the default family handler (see \amref{mac:handler}) executed unless they contain one of the commands \hhx'{\PassOptionsToClass, \PassOptionsToPackage}. \start{newmacro}[\XDeclareOptions] \XDeclareOptions<|nang(fam)>{|nang(opts)}[|nang(default)]{|nang(fn)} @@ -411,7 +417,7 @@ The command \fx{\XInvalidOptionHandler} defines, for each family \ang{fam} in \a \finish{newmacro} \fxim*{\XDeclareCommandOption} -The command \fx{\XDeclareCommandOption} will, apart from declaring the option \ang{opt}, also create a macro \fnl{{pref}{opt}} to hold the user-supplied value of the option. The macro so created can be used in \ang{fn} or in any other place. The default value of the optional \ang{pref} is \quotedfx{\@currname @} prefixed with the letters \fx{cmd}. +The command \fx{\XDeclareCommandOption} will, apart from declaring the option \ang{opt}, also create a macro \fnl{{pref}{opt}} to hold the user-supplied value of the option. The macro so created can be used in \ang{fn} or in any other place. The default value of the optional \ang{pref} is \quotedFx{\@currname @} prefixed with the letters \fx{cmd}. \start{newmacro}[\XDeclareCommandOptions] \XDeclareCommandOptions<|nang(fam)>{|nang(opts)}[|nang(default)]|(|nang(pref)|){|nang(fn)} @@ -426,7 +432,7 @@ The command \fx{\XDeclareCommandOptions} is similar to \fx{\XDeclareCommandOptio \finish{newmacro} \fxim*{\XDeclareBooleanOption} -The command \fx{\XDeclareBooleanOption} will, apart from declaring the option \ang{opt}, also create a boolean \fnl{{if}{pref}{opt}}. It will automatically toggle this boolean (to \hx{true} or \hx{false}) when the option is set and the input is valid, depending on the user-supplied value of the option. The macros so created can be used in \ang{fn} or in any other place. The default value of the optional \ang{pref} is \quotedfx{\@currname @} with no additional prefix. Only \hx{true} or \hx{false} may be submitted as the value of a boolean option. +The command \fx{\XDeclareBooleanOption} will, apart from declaring the option \ang{opt}, also create a boolean \fnl{{if}{pref}{opt}}. It will automatically toggle this boolean (to \hx{true} or \hx{false}) when the option is set and the input is valid, depending on the user-supplied value of the option. The macros so created can be used in \ang{fn} or in any other place. The default value of the optional \ang{pref} is \quotedFx{\@currname @} with no additional prefix. Only \hx{true} or \hx{false} may be submitted as the value of a boolean option. \start{newmacro}[\XDeclareBooleanOptions] \XDeclareBooleanOptions<|nang(fam)>{|nang(opts)}[|nang(default)]|(|nang(pref)|){|nang(fn)} @@ -444,6 +450,50 @@ The command \fx{\XDeclareBooleanOptions} is similar to \fx{\XDeclareBooleanOptio The command \fx{\XDeclareBiBooleanOptions} declares the two options \ang{opt1} and \ang{opt2} in the comma-separated list of options. Again, each of the two declared options is defined with the same family \ang{fam} and default value \ang{default}, but separate functions \ang{fn1} and \ang{fn2}. A distinguishing characteristic of bi-boolean options is that when one option is \hx{true}, the partner option is automatically turned \hx{false}, and vice versa. +\start{newmacro}[\XDeclareSwitchOption] +\XDeclareSwitchOption<|nang(fam)>{|nang(opt)}[|nang(default)]|(|nang(pref)|){|nang(fn)} +\finish{newmacro} +\fxim*{\XDeclareSwitchOption} + +In the parlance of the \pkg'{catoptions,ltxtools}, a switch can assume only one of the two possible states: \fx{\cpttrue} (which is defined as \fx{00}) or \fx{\cptfalse} (which is defined as \fx{01}). A switch \fx{\swa} can be tested with \tex's \hx{\if} conditional. For example, we can do \hx{\if}\unskip\fx{\swa...}\hx{\fi}. The \pkg'{catoptions} also provides the commands \ffx'{\ifswitchTF,\ifswitchFT} for testing switches, which can be used as follows: + +\start+{newmacro}[\ifswitchTF,\ifswitchFT] +\ifswitchTF{|nang(switch)}{|nang(true text)}{|nang(false text)} +\ifswitchFT{|nang(switch)}{|nang(false text)}{|nang(true text)} +\finish{newmacro} +\fxim*{\ifswitchTF,\ifswitchFT} + +Note that here \ang{switch} has no escape character, unless it evaluates to a switch name. So, after defining \fx{\def\swa{00}} we could then do \fx{\ifswitchTF{swa}{true}{false}}. It is somewhat risky to introduce new switches with \hx{\def} or \hx{\let}\footnote{Because of the need to do, \eg, \fx{\let\swa\cpttrue} and \hx{\if}\unskip\fx{\swa} for any given switch \fx{\swa}, switches, unlike toggles, don't have their own separate name space and it is all too easy to redefine an existing switch.}. It is advisable to use \fx{\newswitch} instead. It has the syntax + +\start{newmacro}[\newswitch] +\newswitch{|nang(switch)}[|nang(state)] +\finish{newmacro} +\fxim*{\newswitch} + +Again, note that here \ang{switch} has no escape character, unless it evaluates to a switch name. \ang{state} can be either \hx{true} or \hx{false}. + +Switches are cheaper than native booleans since each switch \fx{swa} has one and only one command \fx{\swa}. Each native boolean \fx{boola}, on the other hand, has up to three commands (namely, \ffx'{\ifboola,\boolatrue,\boolafalse}. If you need to declare a large number of native booleans, it is advisable to consider using switches instead. + +It is possible to toggle the state of a switch by simply using the commands: + +\start+{newmacro}[\setswitchtrue,\setswitchfalse] +\setswitchtrue{|nang(switch)} + |tto |C(if switch) |A(switch) |C(exists, do) \let\switch\cpttrue +\setswitchfalse{|nang(switch)} + |tto |C(if switch) |A(switch) |C(exists, do) \let\switch\cptfalse +\finish{newmacro} +\fxim*{\setswitchtrue,\setswitchfalse} + +The command \fx{\XDeclareSwitchOption} will, apart from declaring the option \ang{opt}, also create a switch \fnl{{pref}{opt}}. It will automatically toggle this switch to \hx{true} (equivalent to \fx{00}) or \hx{false} (equivalent to \fx{01}) when the option is set and the input is valid, depending on the user-supplied value of the option. The macros so created can be used in \ang{fn} or in any other place. The default value of the optional \ang{pref} is again \quotedFx{\@currname @} with no additional prefix. Only \hx{true} or \hx{false} may be submitted as the value of a switch option. + +\start{newmacro}[\XDeclareSwitchOptions] +\XDeclareSwitchOptions<|nang(fam)>{|nang(opts)}[|nang(default)]|(|nang(pref)|){|nang(fn)} +\finish{newmacro} +\fxim*{\XDeclareSwitchOptions} + +The command \fx{\XDeclareSwitchOptions} is similar to \fx{\XDeclareSwitchOption} but, instead of declaring just one option, it declares all the options in the comma-separated list \ang{opts}. Again, each option in the list \ang{opts} is defined with the same family \ang{fam}, default value \ang{default}, and function \ang{fn}. + + \start{newmacro}[\XExecuteOptions] \XExecuteOptions<|nang(fams)>{|nang(opts)}[|nang(na)] \finish{newmacro} @@ -458,7 +508,7 @@ This macro will not use the declaration done by \xdecs when undeclared options a \finish{example} \dummyfxi*{\XExecuteOptions} -This initializes the option \hx{\leftmargin} of \macref{mac:leftmargin} to 0pt. +This initializes the option \hx{\leftmargin} of \amref{mac:leftmargin} to 0pt. \start{newmacro}[\XProcessOptions] \XProcessOptions<|nang(fams)>[|nang(na)] @@ -517,7 +567,7 @@ The implementation here differs significantly from the \latex kernel's scheme of \XExecuteOptions{boola,boolb} \XProcessOptions|*\relax \LoadClass{article} -\cptloadpackages{% +\cptloadpackages{%|label(mac:loadpkg) |nang(pkg name)|rv|nang(pkg opts)|rv|nang(pkg date)|R(;)...|R(;)|nang(more packages) } \endinput @@ -542,6 +592,7 @@ The implementation here differs significantly from the \latex kernel's scheme of Blackberry bush ... blackberry-lily. \end{document} \finish{example} +\fxim*{\cptloadpackages} \start{newmacro}[\ifoptdefTF] @@ -582,7 +633,7 @@ The command \fx{\XLogDisabledOptions}, which can be called before and after \hx{ \docsection(sec:normalize){Normalizing csv and kv lists} -Any arbitrary parser-separated-values list can be normalized by means of the package command \fx{\csv@@normalize} before processing the list. +Any arbitrary parser-separated-values (csv) list can be normalized by means of the package command \fx{\csv@@normalize} before processing the list. \start{newmacro}[\csv@@normalize] \csv@@normalize[|nang(parser)]{|nang(list)} @@ -630,19 +681,25 @@ The command \fx{\kv@@normalize} normalizes a list of key-value pairs, returning \csv@@parse[|nang(parser)][|nang(list)] \csv@@parse|*[|nang(parser)][|nang(listcmd)] \kv@@loop[|nang(parser)][|nang(list)] -\kv@@loop*[|nang(parser)][|nang(listcmd)] +\kv@@loop|*[|nang(parser)][|nang(listcmd)] \kv@@parse[|nang(parser)][|nang(list)] \kv@@parse|*[|nang(parser)][|nang(listcmd)] \finish{newmacro} -\fxim*{\csv@@parse,\kv@@parse,\csv@@loop,\kv@@loop} - -The macros \ffx'{\csv@@parse,\kv@@parse} (and their \stform+) call \ffx'{\csv@@normalize, \kv@@normalize}, respectively. On the other hand, the macro \fx{\csv@@loop} and its \stform don't call \fx{\csv@@normalize} (since not every list will require normalization). This is the only difference between \fx{\csv@@loop} and \fx{\csv@@parse}. The macros \fx{\csv@@loop} and \fx{\csv@@parse} are meant for general csv-list processing with an arbitrary parser, while the command \fx{\kv@@parse} is designed for processing key-value lists. These macros loop over a given \ang{parser}-separated \ang{list} and execute the user-defined, one-parameter commands \ffx'{\csv@do,\kv@do}, respectively, for every item in the list, passing the item as an argument and preserving outer braces. - -The commands \ffx'{\csv@@loop,\csv@@parse,\kv@@parse} aren't expandable. White spaces before and after the list separator are always ignored. If an item contains \ang{parser} or starts with a space, it must be wrapped in curly braces. The braces will persist thereafter, but will of course be removed during printing (if the items are printed). The default value of \ang{parser} is \qcomma. - -The starred variants of \ffx'{\csv@@parse,\kv@@parse} expand \ang{listcmd} once before commencing the loop. - -Empty entries in \ang{list} or \ang{listcmd} will be processed if the boolean \fx{@useempty} is true. You may thus issue the command \fx{\UseEmptyEntry} or \fx{\DiscardEmptyEntry} before commencing the iteration. Issuing any of these commands prior to the commencement of the loop is recommended, because a previous call to either \fx{\csv@@parse} or \fx{\kv@@parse} (perhaps by another package) could have set \fx{@useempty} to a state that is no longer valid or desired. Both \ffx'{\csv@@parse,\kv@@parse} will execute at least once for empty \ang{list} or \ang{listcmd}. Both commands \ffx'{\csv@@parse,\kv@@parse} can be nested to any level and can be mixed. +\fxim*{\csv@@loop,\csv@@parse,\kv@@loop,\kv@@parse} + +The macros \ffx'{\csv@@parse,\kv@@parse}---and their \stform+---call \ffx'{\csv@@normalize, \kv@@normalize}, respectively. On the other hand, the macros \ffx'{\csv@@loop,\kv@@loop} and their \stform+ don't call \fx{\csv@@normalize} (since not every list will require normalization). This is the only difference between \fx{\csv@@loop} and \fx{\csv@@parse}, and between \fx{\kv@@loop} and \fx{\kv@@parse}. The macros \ffx'{\csv@@loop,\csv@@parse} are meant for general csv-list processing with an arbitrary parser, while the command \ffx'{\kv@@loop,\kv@@parse} are designed for processing key-value lists. These macros loop over a given \ang{parser}-separated \ang{list} and execute the user-defined, one-parameter, commands \ffx'{\csv@do,\kv@do}, respectively, for every item in the list, passing the item as an argument and preserving outer braces. The default value of \ang{parser} is \qcomma. The \stform+ of these commands expand \ang{listcmd} once before commencing the loop. + +Here are some points to note about these list processors: +\begin{enum} +\item The commands \ffx'{\csv@@loop,\csv@@parse,\kv@@loop,\kv@@parse} aren't expandable. +\item If an item contains \ang{parser}, it must be wrapped in curly braces when using \ffx'{\csv@@loop,\csv@@parse,\kv@@loop,\kv@@parse}, otherwise the elements may be mixed up during parsing. The braces will persist thereafter, but will of course be removed during printing (if the items are printed). +\item White spaces before and after the list separator are always ignored by the normalizer called by \ffx'{\csv@@parse,\kv@@parse}. If an item contains \ang{parser} or starts with a space, it must, therefore, be wrapped in curly braces before commencing these loops. +\item Since \ffx'{\csv@@loop,\kv@@loop} don't call the normalizer, they preserve outer/surrounding spaces in the entries. Empty entries in \ang{list} or \ang{listcmd} will be processed by \ffx'{\csv@@loop,\kv@@loop} if the boolean \fx{cpt@useempty} is true. You may thus issue the command \fx{\UseEmptyEntry} or \fx{\DiscardEmptyEntry}, which are based on the boolean \fx{cpt@useempty}, before commencing the iteration. If empty entries are important to the task at hand, then issuing \fx{\UseEmptyEntry} or \fx{\DiscardEmptyEntry} prior to the commencement of the loop is recommended, because a previous call to either \fx{\csv@@loop} or \fx{\kv@@loop} (perhaps by another package) could have set \fx{cpt@useempty} to a state that is no longer valid or desired. +\item The commands \ffx'{\csv@@loop,\csv@@parse,\kv@@loop,\kv@@parse} will execute at least once for empty \ang{list} or \ang{listcmd}. +\item The commands \ffx'{\csv@@loop,\csv@@parse,\kv@@loop,\kv@@parse} can be nested to any level and can be mixed. +\item In the commands \ffx'{\csv@@loop,\csv@@parse,\kv@@loop,\kv@@parse}, it is always possible to break out of the loop prematurely at any level of nesting, simply by issuing the command \fx{\loopbreak} (see the example below). Breaking an inner loop doesn't affect the continuation of the outer loop, and vice versa; that is, loop breaks are nesting level-dependent. +\item The user can insert \fx{\csvbreak} as an element in \ang{list} for any of the commands \ffx'{\csv@@loop, \csv@@parse, \kv@@loop, \kv@@parse, \dofunclist} with the hope of automatically breaking out of the list processing prematurely (\ie, before the list is exhausted). The tokens \ffx'{\listbreak, \breaklist} are not defined or used by the \pkg'{catoptions}, to avoid name clashes with other packages. The \pkg'{catoptions} instead uses \fx{\csvbreak}, which is an unexpandable token; if it were to be expandable, then experience has shown that a chaotic infinite loop could arise in an expansion context. Breaking out of the loop prematurely on the current nesting level doesn't affect the continuation of the loop on the other levels. +\end{enum} \start{example}[\csv@@parse] \begingroup @@ -658,50 +715,192 @@ Empty entries in \ang{list} or \ang{listcmd} will be processed if the boolean \f \csv@@parse*[;]\x |com(\show\x@ii) -\def\xa{a,b,c} -\def\xb{x;y;z} +\def\xa{a , {b} , c} +\def\xb{x ; y ; {z}} \def\csv@do#1{% \pushnumber\nra \csn@edef{arg@\romannumeral\nra}{#1}% \chardef\nrb\z@ \def\csv@do##1{% \pushnumber\nrb - \csn@edef{arg@\romannumeral\nra @\romannumeral\nrb}{#1,##1}% + |com(Breaking the inner loop here doesn't affect the outer loop:) + \ifnum\nrb>\@ne|R(\loopbreak)\fi + \csn@def{arg@\romannumeral\nra @\romannumeral\nrb}{#1,##1}% }% \csv@@parse*[;]\xb } \csv@@parse*\xa \finish{example} +\start+{example}[Using \csvbreak] +\newvariables{count}{m@,n@} +\def\csv@do#1{% + \advance\m@\@ne\n@\z@ + \def\csv@do##1{% + \advance\n@\@ne + \csn@def{w@\romannumeral\m@ @\romannumeral\n@}{#1,##1}% + }% + \csv@@parse[;]{ {x} ; {y} ; |R(\csvbreak) ; z }% +} +\csv@@parse{ a , {b}, {c} } +\finish{example} +\fxim*{\csvbreak} + The following is a pseudocode that depicts the use of \fx{\kv@@parse}: \start{example}[\kv@@parse] \def\kv@do#1{% \def\CurrentOption{#1}% - if \CurrentOption is not empty then - split \CurrentOption into option and value; - search if option exists in \@declaredoptions; - if option is found then + |R(if \CurrentOption is not empty then) + Split \CurrentOption into option and value; + Search if option exists in \@declaredoptions + |R(if option is found then) Execute the option's function - else + |R(else) Report option as unknown - fi - fi + |R(fi) + |R(fi) } -|com(\kv@@parse will normalize \@classoptions before parsing it:) -if there are declared options then +|com(|fx(\kv@@parse) will normalize |hx(\@classoptions) before parsing it:) +|R(if there are declared options then) \kv@@parse*\@classoptions -fi +|R(fi) +\finish{example} + +\start{newmacro}[\dofunclist] +\def\do|nang(params){|nang(fn)} +\dofunclist[|nang(parser)]{|nang(list)} +\dofunclist|*[|nang(parser)]{|nang(listcmd)} +\finish{newmacro} +\fxim*{\dofunclist,\do} + +The \fx{\dofunclist} command can be used to iterate over a \ang{parser}-separated \ang{list} or \ang{listcmd} and execute the auxiliary command \fx{\do} for every item in the list, passing the item as an argument and preserving outer braces. While the user-defined commands \ffx'{\csv@do,\kv@do} (required by \ffx'{\csv@@loop,\csv@@parse,\kv@@loop,\kv@@parse}) must be one-parametered, the command \fx{\do} (required by \fx{\dofunclist}) can be multi-parametered. The command \fx{\dofunclist} isn't expandable. \ang{params} are the parameter texts for the command \fx{\do}. White spaces before and after the list separator are always ignored, because the list is first normalized before parsing by \fx{\dofunclist}. If an item contains \ang{parser} or starts with a space, it must be wrapped in curly braces (to preserve the parser or space). The braces may persist thereafter, but will of course be removed during printing (if the items are printed). The default value of \ang{parser} is \qcomma. + +Empty entries in \ang{list} will be ignored by the normalizer called by \fx{\dofunclist}. Such empty entries, if needed later, would need to be enclosed in curly braces before commencing the iteration. The \fx{\dofunclist} command, like all the looping macros of this section, can be nested to any level. + +\start+{example}[\dofunclist] +\def\do#1{\item #1} +\begin{itemize} + |com(The following parser |(,|) is superfluous since the default is comma:) + \dofunclist[,]{aaaa, bbbb, {cccc, dddd}, eeee} +\end{itemize} + +|com(Let us load many packages compactly here. This is just an example of) +|com(|fx(\dofunclist); you can instead use the more appropriate command) +|com(|fx(\cptloadpackages) to load packages (see |amref(mac:loadpkg)):) +\def\do#1#2[#3]{% + \@ifpackageloaded{#1}{% + \@ifpackagelater{#1}{#2}{}{% + \cpt@warn{Older version of package `#1' loaded earlier}% + }% + }{% + \usepackage[#3]{#1}[#2]% + }% +} +|com(The default parser |(,|) is implied below:) +\dofunclist{% + {yfonts}{2003/01/08}[], + {pifont}{2005/04/12}[], + {helvet}{2005/04/12}[scaled=0.9], + {zref}{2008/10/01}[user,lastpage], + {xcolor}{2007/01/21}[table,hyperref] +} + +|com(An example of nested loops follows. Here outer braces in the) +|com(elements are preserved:) +\chardef\m@\z@ +\def\do#1{% + \pushnumber\m@ + \chardef\n@\z@ + \def\do##1{% + \pushnumber\n@ + \ifnum\n@>\@ne|R(\loopbreak)\fi + \csn@def{w@\romannumeral\m@ @\romannumeral\n@}{#1,##1}% + }% + \dofunclist[;]{x;{y};z}% +} +\dofunclist[,]{a,{b},c,d,e} \finish{example} +While \fx{\dofunclist} allows the user to define and call multi-parametered \fx{\do} functions, outer curly braces in the \emph{individual} arguments of \fx{\do} may, in some rare cases, be lost in parsing (but only if the number of arguments exceeds one). This possibility depends on how the parameters and arguments of the user-supplied command \fx{\do} are arranged. If preserving braces is essential to the user's need, then he/she might consider using the more robust commands \ffx'{\csv@@loop, \csv@@parse, \kv@@loop, \kv@@parse}. It is possible to robustly build a multi-parametered callback in the user-defined commands \ffx'{\csv@do,\kv@do} required by \ffx'{\csv@@loop, \csv@@parse, \kv@@loop, \kv@@parse}. Admittedly, only experienced \texnicians may be able to do that. + + +\docsubsection(sec:indris){Looking ahead in csv lists} + +Imagine an instance in which, while processing a csv list, you need not only the current item of the list but also the next item. Moreover, you need to know when the last item of the list has been reached, so that, for example, you can do something peculiar with the last item. The \fx{\indrisloop} list processor provides facilities to accomplish these tasks. + +\start+{newmacro}[\indrisloop] +\indrisloop[|nang(parser)]{|nang(list)}|A(fn) +\indrisloop|*[|nang(parser)]|nang(listcmd)|A(fn) +\finish{newmacro} +\fxim*{\indrisloop,\indrisdepth,\currindris,\currindris@i, +\nextindris,\nextindris@i,\indrisnr,\iflastindris} +\fxi*{\ifloopbreak} + +The \fx{\indrisloop} command can be used to iterate over a \ang{parser}-separated \ang{list} or \ang{listcmd} and execute the user-supplied one-parameter command \ang{fn} for every item in the list, passing the item as an argument and preserving outer braces. + +The \fx{\indrisloop} iterator is of particular interest. The loop provides the macros \ffx'{\indrisdepth, \currindris, \currindris@i, \nextindris, \nextindris@i, \indrisnr, \iflastindris, \ifloopbreak}, which mean, respectively, the current nesting depth/level, the current item on the current level, the current item on an arbitrary level \quotedfx{i}, the next item on the current level, the next item on an arbitrary level \quotedfx{i}, the numerical order of the current item on the current level, the boolean that indicates that the last item of the list has been reached on the current level of nesting, and the boolean that can be used to break the loop prematurely (before the list is exhausted) on any level. +You can do \fx{\iflastindris...\fi} on any level. On any given level, it is possible to break out of the current loop by simply issuing \fx{\loopbreak}. This would not affect the progress of the loops on other levels. When \fx{\iflastindris} is true on a given level \quotedfx{i}, then \ffx'{\nextindris,\nextindris@i} are empty on that level, but not necessarily the macros \ffx'{\currindris,\currindris@i}. + +The following provides a simple application of \fx{\indrisloop}, which I posted on \href{https://groups.google.com/forum/#!forum/comp.text.tex}{comp.text.tex} in July~2011. + +\start{example}[\indrisloop] +\makeatletter +\robust@def*\and@or@comma{% + \ifnumcmpTF\indrisnr>\@ne{% + \ifboolTF{lastindris}{% + \xifstrcmpTF\sav@lastrefsep{and}{ and }{, }% + }{, }% + }{}% +} +\robust@def*\lastrefsep#1{% + \ifstrcmpTF{#1}{and}{}{% + \ifstrcmpTF{#1}{comma}{}{% + \ifstrcmpTF{#1}{,}{}{% + \@ltx@err{Invalid argument for \string\lastrefsep}\@ehc + }% + }% + }% + \gdef\sav@lastrefsep{#1}% +} +\robust@def*\secref{\secref@i{\S}{\S\S}} +\new@def*\secref@i#1#2#3{% + \begingroup + \def\reserved{#3}% + \csv@@normalize*[,]\reserved + \def\do##1{\and@or@comma\ref{##1}}% + \def\reserved@a##1,##2,##3\@nil{% + \ifblankTF{##1}{}{% + \ifblankTF{##2}{% + #1~\ref{##1}% + }{% + #2~\indrisloop*\reserved\do + }% + }% + }% + \expandafter\reserved@a\reserved,,\@nil + \endgroup +} +\begin{|R(document)} +\lastrefsep{and} % or \lastrefsep{comma} +\section{aaa}\label{sec:aaa} +\section{bbb}\label{sec:bbb} +\section{ccc}\label{sec:ccc} +\section{ddd} +\noindent\secref{sec:aaa,sec:bbb,sec:ccc}. +\par\noindent\secref{sec:aaa} +\end{|R(document)} +\finish{example} + +%\bigskip \docsection(sec:tsvparse){Parsing \headq{tsv} lists} \start+{newmacro}[\tsv@@parse,\tsv@@loop] -\tsv@@loop[|nang(list)] -\tsv@@loop|*[|nang(listcmd)] -\tsv@@parse[|nang(list)] -\tsv@@parse|*[|nang(listcmd)] +\tsv@@loop{|nang(list)} +\tsv@@loop|*|nang(listcmd) +\tsv@@parse{|nang(list)} +\tsv@@parse|*|nang(listcmd) \finish{newmacro} \fxim*{\tsv@@parse,\tsv@@loop} @@ -711,7 +910,9 @@ The macros \ffx'{\tsv@@loop,\tsv@@parse} (and their \stform+) of course don't ca The starred variants of \ffx'{\tsv@@loop,\tsv@@parse} expand \ang{listcmd} once before commencing the loop. -Empty entries in \ang{list} or \ang{listcmd} will be processed if the boolean \fx{@useempty} is true. You may thus issue the command \fx{\UseEmptyEntry} or \fx{\DiscardEmptyEntry} before commencing the iteration. Both commands \ffx'{\tsv@@loop,\tsv@@parse} can be nested to any level and can be mixed. +Empty entries in \ang{list} or \ang{listcmd} will be processed if the boolean \fx{cpt@useempty} is true. You may thus issue the command \fxi{\UseEmptyEntry} or \fxi{\DiscardEmptyEntry} before commencing the iteration. Both commands \ffx'{\tsv@@loop,\tsv@@parse} can be nested to any level and can be mixed. + +In the commands \ffx'{\tsv@loop,\tsv@@parse}, it is always possible to break out of the loop prematurely at any level of nesting by issuing the command \fx{\loopbreak}. Again, breaking an inner loop doesn't affect the continuation of the outer loop, and vice versa. The user can insert \fx{\tsvbreak} as an element in \ang{list} for any of the commands \ffx'{\tsv@@loop, \tsv@@parse} so as to automatically break out of the list processing prematurely (\ie, before the list is exhausted). \start+{example}[\tsv@@loop,\tsv@@parse] \newcount\m @@ -722,7 +923,7 @@ Empty entries in \ang{list} or \ang{listcmd} will be processed if the boolean \f \advance\n\@ne \csn@edef{w@\romannumeral\m @\romannumeral\n}{#1,##1}% }% - \tsv@@loop{ x {y} z }% + \tsv@@loop{ x {y} |R(\tsvbreak) z }% } \tsv@@loop{ a {b} {c} } \finish{example} @@ -733,15 +934,18 @@ Empty entries in \ang{list} or \ang{listcmd} will be processed if the boolean \f The following change history highlights significant changes that affect user utilities and interfaces; mutations of technical nature are not documented in this section. The numbers on the right-hand side of the following lists are section numbers; the \stsign means the subject features in the package but is not reflected anywhere in this user guide. \begin{versionhist} + \begin{version}{0.2.5}{2011/07/20} + \item Enlarged the command \fxi{\newvariables} to include \hx{\newwrite} and \fx{\newswitch} \vsecref* + \end{version} \begin{version}{0.2.4}{2011/07/04} - \item Changes to command \fxi{\cptonlypreamble}. \secref* + \item Changes to command \fxi{\cptonlypreamble} \vsecref* \end{version} \begin{version}{0.2c}{2011/06/08} - \item Modified syntax for the handler of unknown options. \secref{sec:options-parse} + \item Modified syntax for the handler of unknown options \vsecref{sec:options-parse} \end{version} \begin{version}{0.2b}{2011/04/02} - \item The following commands have been introduced \secref{sec:options-parse} + \item The following commands have been introduced \vsecref{sec:options-parse} \start{veritem} \XDeclareInvalidOptions \XUnknownOptionHandler \XDisableOptions \XLogDisabledOptions \ifoptdisabledTF \ifoptdefTF @@ -749,8 +953,8 @@ The following change history highlights significant changes that affect user uti \end{version} \begin{version}{0.2a}{2011/02/15} - \item For efficiency reasons, canonical control sequences for futurelet characters are no longer defined automatically. The user is now responsible for specifying the canonical control sequences that should be defined.\secref{sec:future-letting} - \item The following plural-form commands have been introduced \secref{sec:options-parse} + \item For efficiency reasons, canonical control sequences for futurelet characters are no longer defined automatically. The user is now responsible for specifying the canonical control sequences that should be defined \vsecref{sec:future-letting} + \item The following plural-form commands have been introduced \vsecref{sec:options-parse} \start{veritem} \XDeclareOptions \XDeclareCommandOptions \XDeclareBooleanOptions \XDeclareBiBooleanOptions -- cgit v1.2.3