From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- macros/latex/contrib/concepts/README | 60 ++ macros/latex/contrib/concepts/concepts.pdf | Bin 0 -> 307423 bytes macros/latex/contrib/concepts/concepts.sty | 793 +++++++++++++++++++++++++++ macros/latex/contrib/concepts/concepts.tex | 404 ++++++++++++++ macros/latex/contrib/concepts/dry.sty | 56 ++ macros/latex/contrib/concepts/packagedoc.cls | 353 ++++++++++++ macros/latex/contrib/concepts/with.sty | 309 +++++++++++ 7 files changed, 1975 insertions(+) create mode 100644 macros/latex/contrib/concepts/README create mode 100644 macros/latex/contrib/concepts/concepts.pdf create mode 100644 macros/latex/contrib/concepts/concepts.sty create mode 100644 macros/latex/contrib/concepts/concepts.tex create mode 100644 macros/latex/contrib/concepts/dry.sty create mode 100644 macros/latex/contrib/concepts/packagedoc.cls create mode 100644 macros/latex/contrib/concepts/with.sty (limited to 'macros/latex/contrib/concepts') diff --git a/macros/latex/contrib/concepts/README b/macros/latex/contrib/concepts/README new file mode 100644 index 0000000000..99bf38b3a7 --- /dev/null +++ b/macros/latex/contrib/concepts/README @@ -0,0 +1,60 @@ +LaTeX Package : concepts v0.0.5 + +Last Modified : 2012-12-18 + +Author : Michiel Helvensteijn (www.mhelvens.net) + +This package helps to keep track of formal `concepts' for a +specific field or document. This is particularly useful for +scientific papers in e.g. physics, mathematics or computer +science. Such papers often introduce several concepts accompanied +by symbols that can represent instances of them. This package +allows you to declare such concepts once, near their first +introduction in the document, and ensures consistent use of their +symbols and names. + +In the near future, this package will integrate with the +glossaries package to provide more functionality and a consistent +experience when using both packages. + +===== Prerequisites ===== + +To use this package, you need at least the following packages +installed: + +* etextools +* nth +* xspace +* xparse +* ltxkeys (2012/11/17) +* xstring + +Most of these will simply exist in your LaTeX distribution. +But it's possible you may not have the right version of ltxkeys +installed, since it recently changed its interface for handling +list-values. You can find the latest version on CTAN. + +In the near future, this package will drop several dependencies. + +===== Installation ===== + +concepts.sty is provided directly in the package archive. Put +it in a place where your LaTeX distribution can find it. + +(concepts.sty is not generated, but manually maintained; you + may use docstrip to remove the documentation, but you don't + have to; it will just work the way it is) + +===== Documentation ===== + +concepts.pdf is provided directly in the package archive. To +generate the documentation yourself, run LaTeX on concepts.tex. + +(concepts.tex does not contain the package code itself; it inputs + concepts.sty directly to document the implementation) + +===== License ===== + +This material is subject to the LaTeX Project Public License. See +http://www.ctan.org/tex-archive/help/Catalogue/licenses.lppl.html +for the details of that license. diff --git a/macros/latex/contrib/concepts/concepts.pdf b/macros/latex/contrib/concepts/concepts.pdf new file mode 100644 index 0000000000..1f4682c3c6 Binary files /dev/null and b/macros/latex/contrib/concepts/concepts.pdf differ diff --git a/macros/latex/contrib/concepts/concepts.sty b/macros/latex/contrib/concepts/concepts.sty new file mode 100644 index 0000000000..e7093ebd7b --- /dev/null +++ b/macros/latex/contrib/concepts/concepts.sty @@ -0,0 +1,793 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \iffalse %%%% +% % +% Copyright (c) 2012 - Michiel Helvensteijn (www.mhelvens.net) % +% % +% http://latex-concepts.googlecode.com % +% % +% This work may be distributed and/or modified under the conditions % +% of the LaTeX Project Public License, either version 1.3 of this % +% license or (at your option) 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. % +% % +% This work has the LPPL maintenance status `author-maintained'. % +% % +% The Current Maintainer of this work is Michiel Helvensteijn. % +% % +% This work consists of the files concepts.tex and concepts.sty. % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \fi %%%% + +% \CheckSum{266} +% +% \CharacterTable +% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +% Digits \0\1\2\3\4\5\6\7\8\9 +% Exclamation \! Double quote \" Hash (number) \# +% Dollar \$ Percent \% Ampersand \& +% Acute accent \' Left paren \( Right paren \) +% Asterisk \* Plus \+ Comma \, +% Minus \- Point \. Solidus \/ +% Colon \: Semicolon \; Less than \< +% Equals \= Greater than \> Question mark \? +% Commercial at \@ Left bracket \[ Backslash \\ +% Right bracket \] Circumflex \^ Underscore \_ +% Grave accent \` Left brace \{ Vertical bar \| +% Right brace \} Tilde \~} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Package Info} % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{concepts}[2012/12/29 0.0.6 + managing names and symbols of document specific formal concepts] +% \end{macrocode} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Packages} % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% These are the packages we'll need. +% +% \begin{macrocode} +\RequirePackage{etextools} +\RequirePackage{nth} +\RequirePackage{xspace} +\RequirePackage{xparse} % 1 +\RequirePackage{ltxkeys}[2012/11/17] % 2 +\RequirePackage{xstring} +% \end{macrocode} +% +% We need a very recent version of |ltxkeys| in order to +% properly handle list-values. Note that |xparse| needs +% to be loaded before |ltxkeys| or things go wrong somehow. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Facilitating Easy Data Access} % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % \begin{macro}{\cnc@d} \marg{identifier} +%%% \begin{macro}{\cnc@g} \marg{identifier}\\\nopagebreak\noindentnext +% +% This package needs to store and retrieve a lot of data. To make +% the rest of the code more readable, we define the following commands. +% They allow a more freeform description of the data. +% +% |\cnc@d| returns a control sequence name that resolves +% to a specific piece of data in |\csname| context. +% We can get access to the data itself by using |\cnc@g|. +% +% \begin{macrocode} +\newcommand*{\cnc@d}[1]{cnc@data@#1} +\newcommand*{\cnc@g}[1]{\csuse{\cnc@d{#1}}} +% \end{macrocode} +% +% Both take an identifier of one the following shapes: +% \begin{itemize} +% \item |concepts| +% \item |concept|\parg{name}|.option|\parg{name} +% \item |concept|\parg{name}|.option|\parg{name}|.given| +% \item |concept|\parg{name}|.option|\parg{name}|.count| +% \item |concept|\parg{name}|.option|\parg{name}|.index|\parg{number} +% \item |symbol|\parg{name}|.concept| +% \end{itemize} +% +%\end{macro}\end{macro}%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Private General Purpose Macros and Toggles} % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% \begin{macro}{\cnc@upper} \marg{string}\\\nopagebreak\noindentnext +% +% We're going to need a command that capitalizes the first +% letter of a string which fully expands its argument. So +% here it is. +% +% \begin{macrocode} +\newcommand*{\cnc@upper}[1]{\ExpandAftercmds\MakeUppercase{#1}} +% \end{macrocode} +% +%\end{macro}%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % \begin{macro}{\cnc@grabnumber} \marg{token sequence containing \#1} +%%% \momarg{number}\\\nopagebreak\noindentnext +% +% This is a command we're going to use for the automatically +% defined short symbol macros later. It has one 'real' +% mandatory argument and then it captures all numerals +% (0\ldots 9) that follow it. These numerals are then +% substituted for all occurrences of \#1 in the mandatory +% argument which is then `returned'. +% +% \begin{macrocode} +\newcommand{\cnc@grabnumber}[1]{% + \def\cnc@dowithnum##1{#1}% + \futuredef[0123456789]{\cnc@@n}% + {\expandafter\cnc@dowithnum\expandafter{\cnc@@n}}% +} +% \end{macrocode} +% +%\end{macro}%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % \begin{macro}{\cnc@csvlistsize} \marg{csvlist} +%%% \marg{command sequence}\\\nopagebreak\noindentnext +% +% This macro takes a comma-separated list of\ldots anything, +% and stores its size in the given macro as a simple decimal +% string. +% +% \begin{macrocode} +\newcounter{cnc@listsize} +\newrobustcmd{\cnc@csvlistsize}[2]{% + \setcounter{cnc@listsize}{0}% + \def\do##1{\stepcounter{cnc@listsize}}\docsvlist{#1}% + \edef#2{\arabic{cnc@listsize}}% +} +% \end{macrocode} +% +%\end{macro}%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Private Specific-purpose Macros} % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % \begin{macro}{\cnc@conceptname} \marg{plural} \marg{capitalized} +%%% \marg{plural} \marg{concept key}\\\nopagebreak\noindentnext +% +% This typesets the name of a specific concept in one of four forms. It +% can be capitalized or not; and it can be singular or plural. We define +% this private macro because there will be two public macros with this +% functionality and we want to define the behavior in only one place. +% +% The first three arguments are |xparse| style booleans. The first and +% third are the same because the public macros allow both orders between +% the |*| and |^| modifiers and we want to have a simple one-to-one +% mapping between their arguments and the arguments of this private macro. +% +% \begin{macrocode} +\newcommand{\cnc@conceptname}[4]{% +% \end{macrocode} +% +% We test if \emph{both} the first and third arguments are true, meaning +% that the public command has two |*| modifiers. If it does, we give a +% package error. +% +% \begin{macrocode} + \ifboolexpr{ test{\IfBooleanTF{#1}} and test{\IfBooleanTF{#3}} }{% + \PackageError{concepts}% + {You used the * modifier twice; once is enough}% + {I will pretend you just used one *.}% + }{}% +% \end{macrocode} +% +% And then we simply typeset the correct value from our datastore. +% +% \begin{macrocode} + \ifboolexpr{ test{\IfBooleanTF{#1}} or test{\IfBooleanTF{#3}} }{% + \IfBooleanTF{#2}% + {\cnc@g{concept(#4).option(Plural)}}% + {\cnc@g{concept(#4).option(plural)}}% + }{% + \IfBooleanTF{#2}% + {\cnc@g{concept(#4).option(Name)}}% + {\cnc@g{concept(#4).option(name)}}% + }% +% \end{macrocode} +% \uninteresting\begin{macrocode} +} +% \end{macrocode} +% +%\end{macro}%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % \begin{macro}{\cnc@conceptsymbol} \marg{concept key} +%%% \marg{index}\\\nopagebreak\noindentnext +% +% This is the private macro which takes a concept key and an index and returns +% the corresponding symbol from our data-store. We use it in the public macros +% that offer this functionality. +% +% The first thing we do is grab the prefix of the second argument that +% consists of numerals. The rest of the argument is simply left in +% the input stream afterwards. +% +% \begin{macrocode} +\newcommand*{\cnc@conceptsymbol}[2]{% + \cnc@grabnumber{% +% \end{macrocode} +% +% We check if an actual numerical value was passed. +% +% \begin{macrocode} + \ifstrempty{##1}{% +% \end{macrocode} +% +% No, we didn't get a numerical index. If there is only one symbol +% allocated to this concept, we don't care and return that symbol. +% +% \begin{macrocode} + \edef\cnc@symbolcount{\cnc@g{concept(#1).option(symbols).count}}% + \ifnumcomp{\cnc@symbolcount}{=}{1}{% + \ensuremath{\cnc@g{concept(#1).option(symbols).index(1)}}% + }% +% \end{macrocode} +% +% If there are multiple symbols, the lack of an index is ambiguous and +% we report a package error. +% +% \begin{macrocode} + {% + \PackageError{concepts}% + {You didn't specify a number, but the '#1' + \MessageBreak concept has more than one symbol + allocated; please\MessageBreak specify a number + to typeset a specific symbol}% + {I will pretend you didn't ask for a symbol here.}% + }% +% \end{macrocode} +% \uninteresting\begin{macrocode} + }% +% \end{macrocode} +% +% Now follows the `else' branch: we did get a numerical index! +% +% \begin{macrocode} + {% +% \end{macrocode} +% +% We check whether it is larger than the number of symbols +% allocated to the concept. +% +% \begin{macrocode} + \edef\cnc@symbolcount{\cnc@g{concept(#1).option(symbols).count}}% + \ifnumcomp{##1}{>}{\cnc@symbolcount}{% +% \end{macrocode} +% +% If it is, we report an `index out of bounds' error. We first prepare an +% appropriate sentence fragment so the error message becomes more readable. +% +% \begin{macrocode} + \edef\cnc@nth{##1\nthSuff0##1\delimiter}% + \ExpandNext\IfStrEq{\cnc@symbolcount}{0}{% + \edef\cnc@somany{no symbols}% + }{\ExpandNext\IfStrEq{\cnc@symbolcount}{1}{% + \edef\cnc@somany{only 1 symbol}% + }{% + \edef\cnc@somany{only \cnc@symbolcount\space symbols}% + }}% + \PackageError{concepts}% + {You asked for the \cnc@nth\space '#1' symbol, + but\MessageBreak the '#1' concept has + \cnc@somany\space allocated}% + {I will pretend you didn't ask for a symbol here.}% +% \end{macrocode} +% \uninteresting\begin{macrocode} + }% +% \end{macrocode} +% +% But if the number is within bounds, great! We just return the stored symbol. +% +% \begin{macrocode} + {% + \ensuremath{\cnc@g{concept(#1).option(symbols).index(##1)}}% + }% +% \end{macrocode} +% \uninteresting\begin{macrocode} + }% +% \end{macrocode} +% +% Now ends our |\cnc@grabnumber| command, and we supply the second argument +% that may contain the numbers. Just in case it's empty, we make sure we +% don't grab anything that comes after the second argument by adding a +% |\relax|. +% +% \begin{macrocode} + }#2\relax% +% \end{macrocode} +% \uninteresting\begin{macrocode} +} +% \end{macrocode} +% +%\end{macro}%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % \begin{macro}{\cnc@conceptsymbols} \marg{concept key} + % \marg{separator} + % \marg{last separator} +%%% \oarg{indices}\\\nopagebreak\noindentnext +% +% This is the private macro which takes a concept key and a +% comma-separated list of symbol-indices and returns a +% string-separated list of corresponding concept symbols from +% our data-store, possibly with a different token as the last +% separator. We use it in the public macros that offer this +% functionality. The last argument is optional to make it +% easier to define our `short' symbol-list command later. +% +% \begin{macrocode} +\newcounter{cnc@separatorcount}% +\NewDocumentCommand{\cnc@conceptsymbols}{m m m O{1}}{% + \def\cnc@result{}% +% \end{macrocode} +% +% \changes{0.0.6}{2012/12/29} +% {removed unnecessary \{\} from the definition which would break +% correct placement of subscript and superscript} +% +% We loop through the list of indices and produce the +% symbols one-by-one. We use a rather ugly trick to +% possibly have a different \meta{last separator}. +% Each separator is stored in a separate macro, and we +% simply redefine the last one after the loop. This causes +% one macro to be defined for every single separator in +% the document, but we don't care, since most of this +% will be rewritten when we switch to \LaTeX3. +% +% \begin{macrocode} + \ifblank{#4}{}{% + \def\do##1{% + \stepcounter{cnc@separatorcount}% + \edef\cnc@sepcsname{cnc@separator\arabic{cnc@separatorcount}}% + \csdef{\cnc@sepcsname}{#2}% + \expandafter\expandafter\expandafter\def\expandafter% + \expandafter\expandafter\cnc@result\expandafter% + \expandafter\expandafter{\expandafter\cnc@result% + \csname\cnc@sepcsname\endcsname% + \cnc@conceptsymbol{#1}{##1}}% + }\docsvlist{#4}% + \edef\cnc@sepcsname{cnc@separator\arabic{cnc@separatorcount}}% + \csdef{\cnc@sepcsname}{#3}% + \ensuremath{\expandafter\@gobble\cnc@result}% + }% +% \end{macrocode} +% \uninteresting\begin{macrocode} +} +% \end{macrocode} +% +%\end{macro}%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % \begin{macro}{\cnc@nameandsymbols} \marg{concept key} + % \marg{star} + % \marg{capitalized} + % \marg{star}\\\nopagebreak + % \marg{separator} + % \marg{last separator} +%%% \marg{indices}\\\nopagebreak\noindentnext +% +% This is the private macro which takes a concept key, a few +% modifiers, a comma-separated list of symbol-indices and +% custom separators and returns a separated list of the corresponding +% concept symbols from our data-store. We use it in the public +% macros that offer this functionality. +% +% \begin{macrocode} +\newrobustcmd{\cnc@nameandsymbols}[7]{% +% \end{macrocode} +% +% We first check if any |*| modifiers were given and, if so, +% generate an error. +% +% \begin{macrocode} + \ifboolexpr{ test{\IfBooleanTF{#2}} or test{\IfBooleanTF{#4}} }{% + \PackageError{concepts}% + {You used the * modifier, but pluralization\MessageBreak + will be decided by the size of the index list}% + {I will pretend you didn't use the * modifier.}% + }{}% +% \end{macrocode} +% +% We then typeset the name of the concept. We check pluralization +% and pass along the capitalization. +% +% \begin{macrocode} + \cnc@csvlistsize{#7}{\cnc@symbollistsize}% + \ifnumcomp{\cnc@symbollistsize}{=}{1}{% + \cnc@conceptname{\BooleanFalse}{#3}{\BooleanFalse}{#1}% + }{% + \cnc@conceptname{\BooleanTrue}{#3}{\BooleanFalse}{#1}% + }% +% \end{macrocode} +% +% Finally, we print the symbol list. We take away any whitespace +% at the end of the name (possible if the name is itself defined +% in terms of a public concept-name command that introduced an +% |\xspace|) and introduce a single space of our own. +% +% \begin{macrocode} + \unskip{} \cnc@conceptsymbols{#1}{#5}{#6}[#7]% +% \end{macrocode} +% \uninteresting\begin{macrocode} +} +% \end{macrocode} +% +%\end{macro}%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Public Macros} % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% We now implement the macros that will be used directly by package users. +% + + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% \begin{macro}{\NewConcept} \marg{concept key} \marg{options}\\\nopagebreak\noindentnext +% +% \changes{0.0.6}{2012/12/29} +% {made the options mandatory} +% +% We now define the |\NewConcept| command. It should (obviously) be robust. +% +% \begin{macrocode} +\newrobustcmd*{\NewConcept}[2]{% +% \end{macrocode} +% +% Is this concept key already defined? If so, we report a package error. +% +% \begin{macrocode} + \xifinlist{#1}{\cnc@g{concepts}}{% + \PackageError{concepts}% + {The concept key '#1' is already taken}% + {I will pretend that this '\protect\newconcept'% + didn't happen.}% + }% +% \end{macrocode} +% +% Otherwise, we start the actual processing of this new concept. +% +% \begin{macrocode} + {% +% \end{macrocode} +% +% We add the concept to the concepts list in our datastore. +% +% \begin{macrocode} + \listcsxadd{\cnc@d{concepts}}{#1}% +% \end{macrocode} +% +% We then check which options were explicitly specified by the user. +% This results in a set of toggles in our datastore, which may +% be used by other code. +% +% \begin{macrocode} + \DeclareRobustCommand*{\cnc@registertoggle}[1]{% + \newtoggle{\cnc@d{concept(#1).option(##1).given}}% + \togglefalse{\cnc@d{concept(#1).option(##1).given}}% + \ltxkeys@newordkey[cnc@toggle]{#1}{##1}[]% + {\toggletrue{\cnc@d{concept(#1).option(##1).given}}}% + }% + \cnc@registertoggle{name}% + \cnc@registertoggle{Name}% + \cnc@registertoggle{plural}% + \cnc@registertoggle{Plural}% + \cnc@registertoggle{namecmd}% + \cnc@registertoggle{symbols}% + \cnc@registertoggle{symbolcmd}% + \ltxkeys@setkeys*[cnc@toggle]{#1}{#2}% +% \end{macrocode} +% +% We now register the concept name options |name|, |Name|, +% |plural| and |Plural|. This is also where we set their default values. +% +% \begin{macrocode} + \ltxkeys@newordkey[cnc]{#1}{name}% + [#1]% + {\csdef{\cnc@d{concept(#1).option(name)}}{##1}}% + \ltxkeys@newordkey[cnc]{#1}{Name}% + [\cnc@upper{\cnc@g{concept(#1).option(name)}}]% + {\csdef{\cnc@d{concept(#1).option(Name)}}{##1}}% + \ltxkeys@newordkey[cnc]{#1}{plural}% + [\cnc@g{concept(#1).option(name)}\unskip s]% + {\csdef{\cnc@d{concept(#1).option(plural)}}{##1}}% + \ltxkeys@newordkey[cnc]{#1}{Plural}% + [\cnc@upper{\cnc@g{concept(#1).option(plural)}}]% + {\csdef{\cnc@d{concept(#1).option(Plural)}}{##1}}% +% \end{macrocode} +% +% We next register the |namecmd| option. Its default value is the +% concept key with a |\| in front of it. Unlike most other options, +% though, we require the option name to be explicitly given by the +% user to actually define the macro. The following code also +% contains the test. +% +% \begin{macrocode} + \expandaftercmds{\ltxkeys@newordkey[cnc]{#1}{namecmd}% + [}{\csname#1\endcsname}]{% + \iftoggle{\cnc@d{concept(#1).option(namecmd).given}}{% +% \end{macrocode} +% +% We register the option value as given. +% +% \begin{macrocode} + \csdef{\cnc@d{concept(#1).option(namecmd)}}{\noexpand##1}% +% \end{macrocode} +% +%%% \vphantom{x}\marginnote{\meta{namecmd}} \movarg{*} \movarg{\textasciicircum} +% \movarg{*} +% \oarg{indices}\\\nopagebreak\noindentnext +% +% \noindent If the option is processed, we define the concept-specific +% name command. We distinguish between two cases: whether an index-list +% was provided or not. +% +% \begin{macrocode} + \NewDocumentCommand{##1}{t* t^ t* +o}{% + \IfValueTF{####4}{% + \cnc@nameandsymbols{#1}{####1}{####2}{####3}% + {,}{$ and $}{####4}% + }{% + \cnc@conceptname{####1}{####2}{####3}{#1}\unskip\xspace% + }% + }% +% \end{macrocode} +% \uninteresting\begin{macrocode} + }{}% + }% +% \end{macrocode} +% +% We now register the |symbols| option. This option expects a list. +% The callback of the following code processes it one symbol at a time. +% And we first initialize the symbol counter to 0 in case the list is +% empty +% +% \begin{macrocode} + \csdef{\cnc@d{concept(#1).option(symbols).count}}{0}% + \ltxkeys@newlistkey[cnc]{#1}{symbols}[]{% +% \end{macrocode} +% +% We check if this particular symbol is already defined. We don't want +% a symbol allocated to different concepts. Or allocated twice to the +% same concept, for that matter. If all is fine, we update the symbol +% counter for this concept, we add the symbol itself and we update +% the reverse map we use for checking duplicates. +% +% \begin{macrocode} + \ifcsundef{\cnc@d{symbol(\detokenize{##1}).concept}}{% + \csedef{\cnc@d{concept(#1)% + .option(symbols)% + .count}}{\ltxkeys@listcount}% + \csdef{\cnc@d{concept(#1)% + .option(symbols)% + .index(\ltxkeys@listcount)}}{##1}% + \csedef{\cnc@d{symbol(\detokenize{##1}).concept}}{#1}% + }% +% \end{macrocode} +% +% If the symbol is already in use we report a package error. +% +% \begin{macrocode} + {% + \PackageError{concepts}% + {The symbol '\detokenize{##1}' is already allocated + to the '\cnc@g{symbol(\detokenize{##1}).concept}' + concept}% + {I will pretend that you did not + try to add this symbol.}% + }% +% \end{macrocode} +% \uninteresting\begin{macrocode} + }% +% \end{macrocode} +% +% We register the |symbolcmd| option. It does not really have a default, +% but we give an empty default so we can test for the empty string inside. +% +% \begin{macrocode} + \ltxkeys@newordkey[cnc]{#1}{symbolcmd}[]{% + \ifblank{##1}{}{% +% \end{macrocode} +% +% We register the option value as given. +% +% \begin{macrocode} + \csdef{\cnc@d{concept(#1).option(symbolcmd)}}{\noexpand##1} +% \end{macrocode} +% +%%% \vphantom{x}\marginnote{\meta{symbolcmd}} \momarg{index}\\\nopagebreak\noindentnext +% +% \noindent If the option is processed, we now define the concept-specific +% `short' command used to typeset one or more of the allocated symbols. It +% doesn't have a conventional argument, but it grabs all numerals following +% it and uses that as an index to the symbol. If a number was not detected, +% we pass control to the |\cnc@conceptsymbols| command, which is still able +% to grab a square bracket delimited list of indices. +% +% \begin{macrocode} + \newrobustcmd*{##1}{% + \cnc@grabnumber{% + \IfInteger{########1}{% + \cnc@conceptsymbol{#1}{########1}% + }{% TODO: check for square bracket (we still may want to report an error) + \cnc@conceptsymbols{#1}{,}{,}% + }% + }% + }% +% \end{macrocode} +% \uninteresting\begin{macrocode} + }% + }% +% \end{macrocode} +% +% Finally, we issue the command to parse and process all options. +% +% \begin{macrocode} + \ltxkeys@launchkeys[cnc]{#1}{#2}% +% \end{macrocode} +% \uninteresting\begin{macrocode} + }% +} +% \end{macrocode} +% +%\end{macro}%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % \begin{macro}{\ConceptOption} \marg{concept key} +%%% \marg{option key}\\\nopagebreak\noindentnext +% +% The point of this command is that it can retrieve any option value +% in an expandable way. That means we can't use |xparse|, but we don't +% need it. +% +% \begin{macrocode} +\newcommand*{\ConceptOption}[2]{% + \cnc@g{concept(#1).option(#2)}% +} +% \end{macrocode} +% +% Unfortunately, as of writing this, not all options are stored in a +% fully expandable way yet. But they will be in a later version. +% +%\end{macro}%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % \begin{macro}{\ConceptName} \movarg{*} \movarg{\textasciicircum} + % \movarg{*} +%%% \marg{concept key}\\\nopagebreak\noindentnext +% +% This implementation simply calls our private macro for retrieving +% the name in one of four forms. +% +% \begin{macrocode} +\NewDocumentCommand{\ConceptName}{t* t^ t* m}{% + \cnc@conceptname{#1}{#2}{#3}{#4}\unskip\xspace% +} +% \end{macrocode} +% +%\end{macro}%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % \begin{macro}{\ConceptSymbol} \marg{concept key} +%%% \oarg{index}\\\nopagebreak\noindentnext +% +% This implementation simply calls our private macro for retrieving +% the symbol with the given index. The index is optional and +% defaults to 1. +% +% \begin{macrocode} +\NewDocumentCommand{\ConceptSymbol}{m O{1}}{% + \cnc@conceptsymbol{#1}{#2}% +} +% \end{macrocode} +% +%\end{macro}%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % \begin{macro}{\ConceptSymbols} \marg{concept key} + % \oarg{separator} + % \oarg{last separator} +%%% \marg{indices}\\\nopagebreak\noindentnext +% +% This implementation simply calls our private macro for retrieving +% the symbol list with the given indices. The index-list is mandatory +% but can be empty. +% +% \begin{macrocode} +\NewDocumentCommand{\ConceptSymbols}{m +O{,} +o m}{% + \IfValueTF{#3}{% + \cnc@conceptsymbols{#1}{#2}{#3}[#4]% + }{% + \cnc@conceptsymbols{#1}{#2}{#2}[#4]% + }% +} +% \end{macrocode} +% +%\end{macro}%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % \begin{macro}{\ConceptNameAndSymbols} \marg{concept key} +%%% \marg{indices}\\\nopagebreak\noindentnext +% +% This implementation simply calls our private macro for typesetting +% the concept name and the symbol list with the given indices. The +% index-list is mandatory and cannot be empty. +% +% \begin{macrocode} +\NewDocumentCommand{\ConceptNameAndSymbols}{t^ m +O{,} +O{$ and $} m}{% + \cnc@nameandsymbols{#2}{\BooleanFalse}{#1}{\BooleanFalse}% + {#3}{#4}{#5}% +} +% \end{macrocode} +% +%\end{macro}%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + diff --git a/macros/latex/contrib/concepts/concepts.tex b/macros/latex/contrib/concepts/concepts.tex new file mode 100644 index 0000000000..70c2c5c1f5 --- /dev/null +++ b/macros/latex/contrib/concepts/concepts.tex @@ -0,0 +1,404 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% Copyright (C) 2012 by Michiel Helvensteijn - www.mhelvens.net % +% % +% http://latex-concepts.googlecode.com % +% % +% This work may be distributed and/or modified under the % +% conditions of the LaTeX Project Public License, either % +% version 1.3 of this license or (at your option) 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. % +% % +% This work has the LPPL maintenance status `author-maintained'. % +% % +% The Current Maintainer of this work is Michiel Helvensteijn. % +% % +% This work consists of the files concepts.tex and concepts.sty. % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\documentclass[a4paper]{packagedoc} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Setup % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\moretexcs{% + NewConcept,ConceptOption,ConceptName,ConceptSymbol,% + ConceptSymbols,ConceptNameAndSymbols,delta,d,product,p,% + prd% +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Global Changes % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\changes{0.0.1}{2012/11/16}{initial version} +\changes{0.0.2}{2012/11/25}{put the package into a .dtx file} +\changes{0.0.3}{2012/12/01}{separated the .dtx file from the .sty file} +\changes{0.0.4}{2012/12/08}{finished the documentation and made a few fixes} +\changes{0.0.5}{2012/12/18}{implemented symbol-list commands and improved documentation} +\changes{0.0.6}{2013/1/1}{made concept `options' mandatory + fixed some spacing bugs} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{document} % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\maketitle + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Introduction and Motivation} % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +Documents with a lot of formal notation (such as papers about mathematics or +theoretical computer science) can introduce a number of concepts that need +to be managed. They'll have \emph{names}, \emph{descriptions} and associated +\emph{symbols} that need to be typeset, as well as \emph{relations} between them. + +I'm now writing my PhD thesis in the field of Theoretical Computer Science. +It will be especially heavy with definitions. I need to make sure that every +symbol is associated with no more than one concept and that all names and +symbols are consistently used. I'll also need to generate a glossary with +this information. But I don't want to manually keep track +of all that. It's error-prone and it takes time. I'd rather focus on the theory. + +There are already techniques and packages that help lighten the load: +% +\begin{itemize} + \item Rather than use any names or symbols directly in the text, declare + a macro for each one. If you ever need to change one, you'll only + have to do it in one place. You'll also be far less likely to + introduce any typos. + \item There are packages out there to keep track of and output a glossary% + \footnote{It is sometimes called a nomenclature. + The distinction is subtle.}. +\end{itemize} + +But I'm not aware of any technique or package to ensure I'm not +using a name or symbol inconsistently, thereby potentially +confusing the reader. And even if there was, using all these techniques at the +same time is still a lot of overhead. + +I wrote the \textsf{concepts} package to automate all this stuff for me. Every +time I introduce a new concept in my thesis I `declare' it once. The package +then defines all necessary macros for me and checks that I'm using them +properly. + +In \textsf{concepts}~\fileversion{}, most of the above already works but it +cannot generate a glossary yet. In future versions, it will interface with +the \textsf{glossaries} package to accomplish this, and more. + +I'm also planning to implement a rudimentary typesystem, to catch even more +kinds of mistakes in symbol usage. Also, I may want to integrate the +|ligature| option from the \textsf{semantic} package, which allows you to +choose arbitrary characters to typeset your symbols in math mode (with some +restrictions). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Usage} % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +Every concept first has to be declared using the |\NewConcept| macro. +Afterwards, its name and associated symbols can by typeset using other macros. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\describemacro{\NewConcept}{ + \marg{concept key} \marg{options} +} + +Every concept needs a unique \meta{concept key}, by which it will be identified +for the rest of the document. This key can also be used to automatically +derive the name of the concept as well as the macro used to typeset the name. + +Then you'll want to add \meta{options}. This argument takes +a comma-separated list of |key=value| pairs. The following is a list of available +options. Note that the option names are case-sensitive: +% +\begin{description} +\item[name] the name of the concept\\ + --- default: \meta{concept key} +\item[Name] the capitalized name of the concept, for use in the beginning of + a sentence\\ + --- default: \meta{name} with the first letter capitalized +\item[plural] the plural form of the name\\ + --- default: \meta{name}|s| +\item[Plural] the capitalized, pluralized name of the concept\\ + --- default: \meta{plural} with the first letter capitalized +\item[namecmd] the `short' command that may be used to typeset the name of + this concept; this option *has* to be specified for + any command to be defined, but the |=value| part may + be omitted to get the default\\ + --- default: |\|\meta{concept key} +\item[symbols] a comma-separated list of symbols that may represent instances + of this concept, delimited by curly brackets\\ + --- default: |{}| (the empty list) +\item[symbolcmd] the `short' command that may be used to typeset a + specific symbol +\end{description} + +Here are a few examples which will also be used to illustrate the other commands: + +\begin{latex-example} +\NewConcept{swproduct}{ + name = software product, % options 'plural', 'Plural' + Name = Software Product, % are implicitly defined + namecmd = \product, % defines \product + symbols = {p}, % p represents a product + symbolcmd = \p % defines \p +} +\end{latex-example} +% +\begin{latex-example} +\let\delta\relax \let\d\relax % I won't be using these +\NewConcept{delta}{ + namecmd, % defines \delta + symbols = {x, y, z}, % x, y and z represent deltas + symbolcmd = \d % defines \d +} +\end{latex-example} + +There are certain restrictions on new concept declarations. You may +not use the same \meta{concept key} more than once. You may not use the same +symbol for more than one concept (this is a feature; the package will +report an error if you do). Also, both \meta{namecmd} and \meta{symbolcmd} are +subject to the rules governing |\newcommand|. They may not be reused, or you +will see a standard \LaTeX{} error. Finally, any value you supply must behave +properly in an expansion-only context, e.g. be robust. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\describemacro{\ConceptOption}{ + \marg{concept key} \marg{option key} +} + +This command can be used to get back any option value given a +specific \meta{concept~key} and \meta{option key}. For example: + +\begin{latex-example-show} +\ConceptOption{delta}{Plural} +\end{latex-example-show} +% +\begin{latex-example-show} +\edef\prd{\ConceptOption{swproduct}{namecmd}}% +{\ttfamily\expandafter\detokenize\expandafter{\prd}}% + expands to ``\prd''. +\end{latex-example-show} + +|\ConceptOption| is `fully expandable', meaning that it can expand at +least down to the value that was given to the option. (This is not (yet) +guaranteed for the other commands.) + +As you can observe from the |\product| example above, options that expect a +command sequence are stored with an accompanying |\noexpand|. That means that +in an |\edef| context, |\ConceptOption| expands down to the stored command but +no further. After that you can expand it further if you wish. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\describemacro{\ConceptName}{ + \movarg{\textasciicircum} \movarg{*} \marg{concept key} +} + +With this command you can typeset the name of the concept with \meta{concept key} +in any of four forms. The |^| modifier gives you the capitalized version. The |*| +modifier gives you the plural version. The combination gives you both. The order +between |^| and |*| doesn't matter. + +\begin{latex-example-show} +\ConceptName^*{delta} can transform a \ConceptName{swproduct}. +\end{latex-example-show} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\describemetamacro{namecmd}{ + \movarg{\textasciicircum} \movarg{*} +} + +This is the `short' version of |\ConceptName|, specific for each concept that +was declared with the |namecmd| option. It supports the same modifiers. + +\begin{latex-example-show} +\delta^* can easily transform a \product. +\end{latex-example-show} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\describemacro{\ConceptSymbol}{ + \marg{concept key} \oarg{symbol index} +} + +This command typesets a specific symbol associated with a a given concept. It is +always typeset in math mode. Specify the concept with the \meta{concept key} +and the symbol with the \meta{symbol index}. + +The index is 1-based and points to a place in the symbol list provided with the +concept options. If a concept has only one allocated symbol the index may be +omitted. If there is more than one symbol, the index is mandatory. + +\begin{latex-example-show} +\product^* have symbols like \ConceptSymbol{swproduct}. +\end{latex-example-show} +% +\begin{latex-example-show} +$\ConceptSymbol{delta}[2] \cdot \ConceptSymbol{delta}[1] = + \ConceptSymbol{delta}[1] \cdot \ConceptSymbol{delta}[2]$ +\end{latex-example-show} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\describemetamacro{symbolcmd}{ + \momarg{symbol index} +} + +This is the `short' version of |\ConceptSymbol|, specific for each concept that +was declared with the |symbolcmd| option. The optional index is given directly +following the command itself. It doesn't need any delimiters. However, you are +allowed to use square brackets. See the list-variation of this short command +below. + +\begin{latex-example-show} +$(\d2 \cdot \d1)(\p) = \d2(\d1(\p)) = \d2(\p') = \p''$ +\end{latex-example-show} + +As you can see, this short construct requires a lot less space than the +full |\ConceptSymbol| command, so its use is recommended for readability. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\describemacro{\ConceptSymbols}{ + \marg{concept key} \oarg{separator} + \oarg{last separator} \marg{symbol indices} +} + +This command typesets a \meta{separator} separated list of symbols associated +with the given concept, optionally with a different \meta{last separator}. Specify +the concept with the \meta{concept key} and the symbol-list with the +\meta{symbol indices}. \meta{separator} defaults to |,| and \meta{last separator} +defaults to \meta{separator}. The whole list is typeset in math mode, so if +you'd like a non-math delimiter, you need to use \verb|$| tokens. + +The indices are 1-based and point to a place in the symbol list provided with the +concept options. The index-list is mandatory, but can be empty. + +\begin{latex-example-show} +The symbols \ConceptSymbols{delta}{1,2,3} represent \delta*. +\end{latex-example-show} +% +\begin{latex-example-show} +$\{\ConceptSymbols{delta}[;]{1,1,1}\}$ contains only \d1. +\end{latex-example-show} +% +\begin{latex-example-show} +What about \ConceptSymbols{delta}[,][$ and $]{3, 2, 1}? +\end{latex-example-show} +% +\begin{latex-example-show} +xx\ConceptSymbols{delta}{}xx +\end{latex-example-show} + +If you need any symbol in the resulting list to have some decoration (like a +prime, subscript or superscript) you can decorate the corresponding index +accordingly. This currently only works for decorations that would be specified +\emph{after} the symbol. Each element of \meta{symbol indices} still needs to +start with the index itself: + +\begin{latex-example-show} +\ldots such as the symbols in + $(\ConceptSymbols{delta}{1_1, 2'', 3^{\d1(\p)}})$. +\end{latex-example-show} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\describemetamacro{symbolcmd}{ + \oarg{symbol indices} +} + +This is the `short' version of |\ConceptSymbols|, specific for each concept that +was declared with the |symbolcmd| option. The \meta{symbol indices} list needs +to be delimited by square brackets as shown below. + +\begin{latex-example-show} +$\forall \d[1,2] \in D:\ \d1 \| \d2\ \Rightarrow\ {} + \exists \d[3'] \in D:\ \d1 \prec \d3' \land \d2 \prec \d3'$ +\end{latex-example-show} +% +\begin{latex-example-show} +xx\d[]xx\p[]xx +\end{latex-example-show} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\describemacro{\ConceptNameAndSymbols}{ + \movarg{\textasciicircum} \marg{concept key} + \oarg{separator} \oarg{last separator} + \marg{symbol indices} +} + +This command is the `hybrid' version of |\ConceptName| and |\ConceptSymbols|. +It typesets the name of the concept followed by a \meta{separator} separated list +of symbols associated with the given concept, optionally with a different +\meta{last separator}. Specify the concept with the \meta{concept key} and the +symbol-list with \meta{symbol~indices}. \meta{separator} defaults to |,| and +\meta{last separator} defaults to |$ and $|. The name is typeset in text mode and +the list is typeset in math mode. + +The indices are 1-based and point to a place in the symbol list provided with the +concept options. The index-list is mandatory and cannot be empty. + +You can still supply the |^| modifier to capitalize the name but the choice +between singular and plural form is determined by the number of \meta{symbol indices}. + +\begin{latex-example-show} +We use \ConceptNameAndSymbols{delta}[,][$ and also $]{1,2,3}. +\end{latex-example-show} + +For some other neat tricks, read the documentation of |\ConceptSymbols| above. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\describemetamacro{namecmd}{ + \movarg{\textasciicircum} \oarg{symbol indices} +} + +This is a `short' version of |\ConceptNameAndSymbols|, +specific for each concept that was declared with the |namecmd| option. +The \meta{symbol indices} list needs to be delimited by square brackets +as shown below. The list is comma-delimited and the last (or only) delimiter is +the word `and'. + +\begin{latex-example-show} +\delta^[1,2] come before \delta[3]. +\end{latex-example-show} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\section{Future Work} % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +Everything up to this version of the package has been a bit of an experiment +for me. A way to get me started. I may still fix one or two issues for the +0.0.x series, but I will soon start from scratch with all I've learned. + +There will be two major changes starting from version 0.1.0. First of all, the +package will be built on top of the |glossaries| package, which already does +much of the work I'm now doing manually. This was always the plan, as we'll +want to typeset a glossary with our concepts, and I don't want to reinvent +the wheel. The |glossaries| package is actively developed and has a great +amount of features we can take advantage of. Secondly, I will program the +0.1.0 series using \LaTeX3. + +Here is an incomplete list of the features I am planning to implement: +\begin{itemize} + \item full integration with the \textsf{glossaries} package + \item typesetting a \emph{summary} of the concepts introduced in each chapter / section + \item management of \emph{tuples} and \emph{sets} of concept instances + \item management of \emph{subconcepts} plus a rudimentary \emph{typesystem} that + ensures concept instances are not used where a different concept is expected +\end{itemize} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\end{document} % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/macros/latex/contrib/concepts/dry.sty b/macros/latex/contrib/concepts/dry.sty new file mode 100644 index 0000000000..fd639991ce --- /dev/null +++ b/macros/latex/contrib/concepts/dry.sty @@ -0,0 +1,56 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \iffalse %%%% +% % +% Copyright (c) 2012 - Michiel Helvensteijn (www.mhelvens.net) % +% % +% http://latex-with.googlecode.com % +% % +% This work may be distributed and/or modified under the conditions % +% of the LaTeX Project Public License, either version 1.3 of this % +% license or (at your option) 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. % +% % +% This work has the LPPL maintenance status `author-maintained'. % +% % +% The Current Maintainer of this work is Michiel Helvensteijn. % +% % +% This work consists of the file dry.sty. % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \fi %%%% + +% I will 'officially' release this package at some point in the future. For +% now I'm just using it to document a couple of packages. Still, it's +% released under LPPL, so use it as you will. +% +% -- Michiel Helvensteijn + +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{dry} + [2012/12/19 convenience macros for reusing LaTeX code] + +\RequirePackage{filecontents} +\RequirePackage{xparse} +\RequirePackage{etoolbox} +\RequirePackage{with} + +\newcommand\minput[1]{% + \input{#1}\unskip% +} + +\NewDocumentCommand{\NewDRYer}{m +m}{% + \with{un} [#1] [#2] {% + \newenvironment{#1}{% + \begingroup% + \@tempswafalse\filec@ntents{##1.tmp}% + }{% + \endfilecontents% + \endgroup% + }% + \AfterEndEnvironment{#1}{% + \with{xn} [##1.tmp] [\minput{##1.tmp}] {% + ##2% + }% + }% + }% +} diff --git a/macros/latex/contrib/concepts/packagedoc.cls b/macros/latex/contrib/concepts/packagedoc.cls new file mode 100644 index 0000000000..1c261b9836 --- /dev/null +++ b/macros/latex/contrib/concepts/packagedoc.cls @@ -0,0 +1,353 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% Copyright (C) 2012 by Michiel Helvensteijn - www.mhelvens.net % +% % +% This work may be distributed and/or modified under the % +% conditions of the LaTeX Project Public License, either % +% version 1.3 of this license or (at your option) 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. % +% % +% This work has the LPPL maintenance status `author-maintained'. % +% % +% The Current Maintainer of this work is Michiel Helvensteijn. % +% % +% This work consists of the file packagedoc.cls. % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\let\packagename\jobname + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Document Class % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\LoadClassWithOptions{ltxdoc} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Importing The Relevant Package % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\RequirePackage{\packagename} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Importing Other Packages % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\RequirePackage{etoolbox} +\RequirePackage[xcolor]{mdframed} +\RequirePackage{marginnote} +\RequirePackage{listings} +\RequirePackage{textcomp} +\RequirePackage[pdftex,colorlinks=true]{hyperref} +\RequirePackage{dry} +\RequirePackage{needspace} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Documentation Options % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\EnableCrossrefs +\CodelineIndex +\RecordChanges + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% File Info % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\GetFileInfo{\packagename.sty} + +\title{The \textsf{\packagename} package\thanks{% + This document corresponds to \textsf{\packagename}~\fileversion, + dated \filedate.% +}} + +\author{ + Michiel Helvensteijn\\ + \href{mailto:mhelvens+latex@gmail.com}{mhelvens+latex@gmail.com} +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Development Info % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newmdenv[ + leftline = false, + rightline = false +]{bannerframe} + +\apptocmd{\maketitle}{ + \begin{bannerframe} + \small + \begin{center} + Development of this package is organized at + \href{http://latex-\packagename.googlecode.com} + {latex-\packagename.googlecode.com}.\\ + I am happy to receive feedback there! + \end{center} + \end{bannerframe} +}{}{} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Skipping Paragraph Indentation After Specific Stuff % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\let\packagedoc@old@par\par + +\newcommand*{\noindentnext}{% + \def\par{% + \packagedoc@old@par% + \noindent% + \let\par\packagedoc@old@par% + }% +} + +\newcommand*{\noindentafterenv}[1]{ + \AfterEndEnvironment{#1}{\noindentnext} +} + +\newcommand*{\noindentaftercmd}[1]{ + \apptocmd{#1}{\noindentnext}{}{ + \ClassError{packagedoc} + {Could not patch \protect#1\space command.} + {Oops! I tried to auto-skip any indentation after the + \protect#1\space command, but I failed somehow.} + } +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Example Environment Setup % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%% Extra keywords for LaTeX +% +\newcommand{\moretexcs}[1]{ + \lstdefinelanguage{latex}{ + language=[LaTeX]tex, + moretexcs={ExplSyntaxOn,ExplSyntaxOff,lstinputlisting,detokenize,#1} + } +} + +%%% Code formatting +% +\lstdefinestyle{examplecode}{% + language=latex,% + basicstyle=\ttfamily\small,% + texcsstyle=*\bfseries,% + upquote=true% +} + + + +%%% Setting up example code block +% +\definecolor{examplecodelinecolor}{rgb}{0,0,0} +\definecolor{examplecodebackgroundcolor}{rgb}{.9,.9,.9} +\newmdenv[ + linecolor = examplecodelinecolor, + backgroundcolor = examplecodebackgroundcolor, + skipabove = 0px, + skipbelow = 0px, + innertopmargin = -3px, + innerrightmargin = 4px, + innerbottommargin = -3px, + innerleftmargin = 4px +]{examplecodeframe} + +%%% Defining example output block +% +\definecolor{exampleoutputbackgroundcolor}{rgb}{1,1,1} +\newmdenv[ + linecolor = examplecodelinecolor, + backgroundcolor = exampleoutputbackgroundcolor, + skipabove = 0px, + skipbelow = 0px, + innertopmargin = 4px, + innerrightmargin = 4px, + innerbottommargin = 4px, + innerleftmargin = 4px +]{exampleoutputframe} + +%%% Macros for counting lines in file, adapted from +%%% http://andreas.scherbaum.la/blog/archives/ +%%% 670-Read-number-lines-in-a-file-in-LaTeX.html +% +\RequirePackage{ifthen} +\newboolean{packagedoc@restfile} +\newcommand*{\packagedoc@fileline}{} +\newread\packagedoc@file +\newcommand*{\packagedoc@readnextline}[1]{% + \ifthenelse{\boolean{packagedoc@restfile}}{% + \read#1 to \packagedoc@fileline% + \ifeof#1\setboolean{packagedoc@restfile}{false}% + \else\fi% + }{}% +} +\newcommand*{\countlinesinfile}[2]{% + \setboolean{packagedoc@restfile}{true}% + \setcounter{packagedoc@linecount}{0}% + \openin\packagedoc@file=#1% + \whiledo{\boolean{packagedoc@restfile}}{% + \packagedoc@readnextline{\packagedoc@file}% + \ifthenelse{\boolean{packagedoc@restfile}}{% + \stepcounter{packagedoc@linecount}% + }{}% + }% + \closein\packagedoc@file% + \edef#2{\thepackagedoc@linecount}% +} + +\newcounter{packagedoc@linecount} +\newlength{\packagedoc@spacetoreserve} + +%%% DRYer without output +% +\NewDRYer{latex-example}{% + \addvspace{4px}% + {% + \ttfamily\small% + \countlinesinfile{#1}{\countedlines}% + \setlength{\packagedoc@spacetoreserve}{\countedlines\baselineskip}% + \addtolength{\packagedoc@spacetoreserve}{-4px}% + \needspace{\packagedoc@spacetoreserve}% + }% + \begin{examplecodeframe}% + \renewcommand{\ttdefault}{pcr}% + \lstinputlisting[style=examplecode]{#1}% + \end{examplecodeframe}% + #2% + \noindentnext% + \addvspace{4px}% +} + +%%% DRYer WITH output but WITHOUT side-effects +% +\NewDRYer{latex-example-show}{% + \addvspace{4px}% + {% + \ttfamily\small% + \countlinesinfile{#1}{\countedlines}% + \setlength{\packagedoc@spacetoreserve}{\countedlines\baselineskip}% + \addtolength{\packagedoc@spacetoreserve}{\baselineskip}% + \needspace{\packagedoc@spacetoreserve}% + }% + \begin{examplecodeframe}% + \renewcommand{\ttdefault}{pcr}% + \lstinputlisting[style=examplecode]{#1}% + \end{examplecodeframe}\vspace{-4px}% + \begin{exampleoutputframe}% + #2% + \end{exampleoutputframe}% + \noindentnext% + \addvspace{4px}% +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Implementation Code Box Setup % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%% Saving old implementation code block font +% +\AtBeginDocument{\let\old@macro@font\macro@font} + +%%% Setup for 'interesting' implementation code blocks +% +\definecolor{interestingcodebackgroundcolor}{rgb}{.9,.9,.9} +\definecolor{interestingcodelinecolor}{rgb}{0,0,0} +\mdfdefinestyle{interestingcode}{ + linecolor = interestingcodelinecolor, + backgroundcolor = interestingcodebackgroundcolor +} +\newcommand*{\interesting}{% + \def\codestyle{interestingcode}% + \def\codeskipabove{5px}% + \let\macro@font\old@macro@font% +} + +%%% Setup for 'UNinteresting' implementation code blocks +% +\definecolor{uninterestingcodebackgroundcolor}{rgb}{.97,.97,.97} +\definecolor{uninterestingcodelinecolor}{rgb}{.5,.5,.5} +\definecolor{uninterestingcodecolor}{rgb}{.4,.4,.4} +\mdfdefinestyle{uninterestingcode}{ + linecolor = uninterestingcodelinecolor, + backgroundcolor = uninterestingcodebackgroundcolor, +} +\newcommand*{\uninteresting}{% + \def\codestyle{uninterestingcode}% + \def\codeskipabove{-5px}% + \def\macro@font{\color{uninterestingcodecolor}\old@macro@font}% +} + +%%% Actually surround 'macrocode' with the frame +% +\surroundwithmdframed[ + style = \codestyle, + skipabove = \codeskipabove, + skipbelow = 5px, + splittopskip = 10px, + splitbottomskip = 4px, + innertopmargin = 4px, + innerrightmargin = 4px, + innerbottommargin = 4px, + innerleftmargin = 4px +]{macrocode} + +\noindentafterenv{macrocode} + +%%% Start out with 'interesting' code status and +%%% always go back to it after one code block +% +\interesting +\AfterEndEnvironment{macrocode}{\interesting} + +%%% No indentation after macrocode block +% +\noindentafterenv{macrocode} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Argument Specifiers and such % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newcommand*{\movarg}[1]{[ \texttt{#1} ]} +\newcommand*{\momarg}[1]{[ \meta{#1} ]} + +\newcommand{\describemacro}[2]{% + \needspace{3\baselineskip}% + \noindent\\\DescribeMacro{#1} #2\\\noindentnext% +} + +\newcommand{\describemetamacro}[2]{% + \needspace{3\baselineskip}% + \noindent\\\marginnote{\meta{#1}} #2\\\noindentnext% +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Other Stuff % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\noindentafterenv{description} +\noindentafterenv{itemize} +\noindentafterenv{enumerate} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Automatic Implementation Docs % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\AtEndDocument{ + \pagebreak + + \section{Implementation} + + \StopEventually {\PrintChanges} + + We now show and explain the entire implementation from \texttt{\packagename.sty}. + + \DocInput{\packagename.sty} + + \Finale + + \PrintIndex +} diff --git a/macros/latex/contrib/concepts/with.sty b/macros/latex/contrib/concepts/with.sty new file mode 100644 index 0000000000..49e16dac49 --- /dev/null +++ b/macros/latex/contrib/concepts/with.sty @@ -0,0 +1,309 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \iffalse %%%% +% % +% Copyright (c) 2012 - Michiel Helvensteijn (www.mhelvens.net) % +% % +% http://latex-with.googlecode.com % +% % +% This work may be distributed and/or modified under the conditions % +% of the LaTeX Project Public License, either version 1.3 of this % +% license or (at your option) 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. % +% % +% This work has the LPPL maintenance status `author-maintained'. % +% % +% The Current Maintainer of this work is Michiel Helvensteijn. % +% % +% This work consists of the file with.sty and with.tex. % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \fi %%%% + +% \CheckSum{0} +% +% \CharacterTable +% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +% Digits \0\1\2\3\4\5\6\7\8\9 +% Exclamation \! Double quote \" Hash (number) \# +% Dollar \$ Percent \% Ampersand \& +% Acute accent \' Left paren \( Right paren \) +% Asterisk \* Plus \+ Comma \, +% Minus \- Point \. Solidus \/ +% Colon \: Semicolon \; Less than \< +% Equals \= Greater than \> Question mark \? +% Commercial at \@ Left bracket \[ Backslash \\ +% Right bracket \] Circumflex \^ Underscore \_ +% Grave accent \` Left brace \{ Vertical bar \| +% Right brace \} Tilde \~} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Package Info} % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e} +\RequirePackage{expl3} +\ProvidesExplPackage{with}{2012/12/23}{0.0.1} + {an inline construct for passing token lists as parameters} +% \end{macrocode} + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Required Packages} % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +% \begin{macrocode} +\RequirePackage{xparse} +\RequirePackage{l3regex} +% \end{macrocode} + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \subsection{Package Code} % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +% \begin{macrocode} +\cs_generate_variant:Nn \cs_generate_variant:Nn {cn} +% \end{macrocode} + + + +% \begin{macrocode} +\cs_new:Nn \gen_use:nn { + \cs_generate_variant:cn + { #1 : \prg_replicate:nn{\tl_count:n{#2}}{n} } + { #2 } + \use:c{ #1 : #2 } +} +% \end{macrocode} + + + +% \begin{macrocode} +\cs_new_protected:Nn \with:n {#1} +\cs_new_protected:Nn \with:nn { + \cs_set:Npn \__with:n ##1 {#2} + \__with:n {#1} } +\cs_new_protected:Nn \with:nnn { + \cs_set:Npn \__with:nn ##1##2 {#3} + \__with:nn {#1}{#2} } +\cs_new_protected:Nn \with:nnnn { + \cs_set:Npn \__with:nnn ##1##2##3 {#4} + \__with:nnn {#1}{#2}{#3} } +\cs_new_protected:Nn \with:nnnnn { + \cs_set:Npn \__with:nnnn ##1##2##3##4 {#5} + \__with:nnnn {#1}{#2}{#3}{#4} } +\cs_new_protected:Nn \with:nnnnnn { + \cs_set:Npn \__with:nnnnn ##1##2##3##4##5 {#6} + \__with:nnnnn {#1}{#2}{#3}{#4}{#5} } +\cs_new_protected:Nn \with:nnnnnnn { + \cs_set:Npn \__with:nnnnnn ##1##2##3##4##5##6 {#7} + \__with:nnnnnn {#1}{#2}{#3}{#4}{#5}{#6} } +\cs_new_protected:Nn \with:nnnnnnnn { + \cs_set:Npn \__with:nnnnnnn ##1##2##3##4##5##6##7 {#8} + \__with:nnnnnnn {#1}{#2}{#3}{#4}{#5}{#6}{#7} } +\cs_new_protected:Nn \with:nnnnnnnnn { + \cs_set:Npn \__with:nnnnnnnn ##1##2##3##4##5##6##7##8 {#9} + \__with:nnnnnnnn {#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8} } +% \end{macrocode} + + + +% \begin{macrocode} +\msg_new:nnnn{with}{invalid-parameter-specs}{ + The~argument~specification~'#1'~is~not~valid. +}{ + The~argument~specification~should~consist~of~between~ + one~and~seven~of~the~letters~'n',~'o',~'f',~'x',~'u'~or~'U'. +} +% \end{macrocode} + + + +% \begin{macrocode} +\msg_new:nnnn{with}{invalid-parameter-number}{ + You~specified~#1~arguments~but~provided~#2. +}{ + Your~argument~specification~is~'#3',~which~means~you~should~ + provide~#1~optional~arguments.~However,~you~provided~only~#2. +} +% \end{macrocode} + + + +% \begin{macrocode} +\tl_new:N \l__with_argspec_tl +\tl_new:c {l__with_p_1_tl} \tl_new:c {l__with_p_2_tl} +\tl_new:c {l__with_p_3_tl} \tl_new:c {l__with_p_4_tl} +\tl_new:c {l__with_p_5_tl} \tl_new:c {l__with_p_6_tl} +\tl_new:c {l__with_p_7_tl} +\tl_new:N \l__with_code_tl +% \end{macrocode} + + + +% \begin{macrocode} +\int_new:N \l__with_arg_int +\cs_new:Nn \__with_param_name: { + l__with_p_ + \int_use:N\l__with_arg_int + _tl +} +% \end{macrocode} + + + +% \begin{macrocode} +\tl_new:N \l__with_unique_counter_tl +\tl_new:N \l__with_param_tl +% \end{macrocode} + + + +% \begin{macrocode} +\cs_generate_variant:Nn \with:nn {xn} +\cs_generate_variant:Nn \with:nnnnnnnnn {oooooooon} +% \end{macrocode} + + + +% \begin{macrocode} +\NewDocumentCommand \with {m +o +o +o +o +o +o +o +m} { +% \end{macrocode} + + + +% \begin{macrocode} + \regex_match:nnF {^[noxfuU]{1,7}$} {#1} + { \msg_critical:nnn{with}{invalid-parameter-specs}{#1} } +% \end{macrocode} + + + +% \begin{macrocode} + \tl_set:Nn \l__with_argspec_tl {#1} + \int_zero:N \l__with_arg_int + \IfValueT{#2} { + \tl_set:cn {l__with_p_1_tl} {#2} \int_incr:N \l__with_arg_int + \IfValueT{#3} { + \tl_set:cn {l__with_p_2_tl} {#3} \int_incr:N \l__with_arg_int + \IfValueT{#4} { + \tl_set:cn {l__with_p_3_tl} {#4} \int_incr:N \l__with_arg_int + \IfValueT{#5} { + \tl_set:cn {l__with_p_4_tl} {#5} \int_incr:N \l__with_arg_int + \IfValueT{#6} { + \tl_set:cn {l__with_p_5_tl} {#6} \int_incr:N \l__with_arg_int + \IfValueT{#7} { + \tl_set:cn {l__with_p_6_tl} {#7} \int_incr:N \l__with_arg_int + \IfValueT{#8} { + \tl_set:cn {l__with_p_7_tl} {#8} \int_incr:N \l__with_arg_int + }}}}}}} + \tl_set:Nn \l__with_code_tl {#9} +% \end{macrocode} + + + +% \begin{macrocode} + \int_compare:nNnF {\tl_count:n{#1}} = {\l__with_arg_int} { + \msg_error:nnxxx{with}{invalid-parameter-number} + { \tl_count:n{#1} } + { \int_use:N \l__with_arg_int } + { #1 } + } +% \end{macrocode} + + + +% \begin{macrocode} + \tl_replace_all:Nnn \l__with_argspec_tl {u} {x} + \tl_replace_all:Nnn \l__with_argspec_tl {U} {c} +% \end{macrocode} + + + +% \begin{macrocode} + \int_zero:N \l__with_arg_int + \tl_map_inline:nn {#1} { + \int_incr:N \l__with_arg_int +% \end{macrocode} + + + +% \begin{macrocode} + \tl_if_in:nnT {uU} {##1} { + \tl_set:Nx \l__with_unique_counter_tl + { g__with_unique_ \use:c{\__with_param_name:} _count_int } + + \int_if_exist:cF {\l__with_unique_counter_tl} + { \int_new:c {\l__with_unique_counter_tl} } + + \int_incr:c {\l__with_unique_counter_tl} + + \tl_put_left:cx {\__with_param_name:} + { g_with_unique_ } + + \tl_put_right:cx {\__with_param_name:} + { _ \int_use:c{\l__with_unique_counter_tl} } + } +% \end{macrocode} + + + +% \uninteresting\begin{macrocode} + } +% \end{macrocode} + + + +% \begin{macrocode} + \with:oooooooon {\l__with_argspec_tl} + {\cs:w l__with_p_1_tl \cs_end:} + {\cs:w l__with_p_2_tl \cs_end:} + {\cs:w l__with_p_3_tl \cs_end:} + {\cs:w l__with_p_4_tl \cs_end:} + {\cs:w l__with_p_5_tl \cs_end:} + {\cs:w l__with_p_6_tl \cs_end:} + {\cs:w l__with_p_7_tl \cs_end:} { + \with:oooooooon {##1o}{##2}{##3}{##4} + {##5}{##6}{##7}{##8} { + \int_case:nnn {\l__with_arg_int} { + {1} { \gen_use:nn{with}{####1} + {####2} {\l__with_code_tl} } + {2} { \gen_use:nn{with}{####1} + {####2}{####3} {\l__with_code_tl} } + {3} { \gen_use:nn{with}{####1} + {####2}{####3}{####4} {\l__with_code_tl} } + {4} { \gen_use:nn{with}{####1} + {####2}{####3}{####4} + {####5} {\l__with_code_tl} } + {5} { \gen_use:nn{with}{####1} + {####2}{####3}{####4} + {####5}{####6} {\l__with_code_tl} } + {6} { \gen_use:nn{with}{####1} + {####2}{####3}{####4} + {####5}{####6}{####7} {\l__with_code_tl} } + {7} { \gen_use:nn{with}{####1} + {####2}{####3}{####4} + {####5}{####6}{####7} + {####8} {\l__with_code_tl} } + }{} + } + } +% \end{macrocode} + + + +% \uninteresting\begin{macrocode} +} +% \end{macrocode} + + -- cgit v1.2.3