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/lmake/README | 15 + macros/latex/contrib/lmake/lmake.dtx | 522 +++++++++++++++++++++++++++++++++++ macros/latex/contrib/lmake/lmake.ins | 55 ++++ macros/latex/contrib/lmake/lmake.pdf | Bin 0 -> 287786 bytes macros/latex/contrib/lmake/lmake.sty | 147 ++++++++++ 5 files changed, 739 insertions(+) create mode 100644 macros/latex/contrib/lmake/README create mode 100644 macros/latex/contrib/lmake/lmake.dtx create mode 100644 macros/latex/contrib/lmake/lmake.ins create mode 100644 macros/latex/contrib/lmake/lmake.pdf create mode 100644 macros/latex/contrib/lmake/lmake.sty (limited to 'macros/latex/contrib/lmake') diff --git a/macros/latex/contrib/lmake/README b/macros/latex/contrib/lmake/README new file mode 100644 index 0000000000..b02f3f9522 --- /dev/null +++ b/macros/latex/contrib/lmake/README @@ -0,0 +1,15 @@ +lmake 2012/02/29 v1.0 +Copyright (C) 2012 by Shengjun Pan panshengjun@gmail.com + +This package (lmake) provides two macros "lcmd" and "lmake" to simplify +typesetting a list of phrases that fit a pattern: + +* \lcmd{command}{prefix}{list} + makes new commands in batch by adding a prefix to an existing command, + each with a different argument taken from a list. + +* \lmake[[key1=]value1,[key2=]value2,...] + makes a list of the form p(i1),p(i2),...,p(in), where teh p(.)'s are + similar phrases that fit a pattern. + +Plese refer to lmake.pdf for more details and examples. diff --git a/macros/latex/contrib/lmake/lmake.dtx b/macros/latex/contrib/lmake/lmake.dtx new file mode 100644 index 0000000000..f8298099f8 --- /dev/null +++ b/macros/latex/contrib/lmake/lmake.dtx @@ -0,0 +1,522 @@ +% \iffalse meta-comment +% +% Copyright (C) 2012 by Shengjun Pan +% ------------------------------------------------------- +% +% This file may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either version 1.2 +% 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.2 or later is part of all distributions of LaTeX +% version 1999/12/01 or later. +% +% \fi +% +% \iffalse +%<*driver> +\ProvidesFile{lmake.dtx} +% +%\NeedsTeXFormat{LaTeX2e}[1999/12/01] +%\ProvidesPackage{lmake} +%<*package> + [2012/02/29 v1.0 .dtx lmake file] +% +% +%<*driver> +\documentclass{ltxdoc} +\usepackage{amsmath,amssymb} +\usepackage[width=5.5in,height=8.6in]{geometry} +\usepackage{multirow} +\usepackage{graphicx} +\usepackage{makeidx} +\usepackage[usenames]{color} +\usepackage{lmake}[2012/02/29] +\EnableCrossrefs +\CodelineIndex +\RecordChanges +\begin{document} + \DocInput{lmake.dtx} + \PrintChanges + \PrintIndex +\end{document} +% +% \fi +% +% \CheckSum{412} +% +% \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 \~} +% +% +% \changes{v1.0}{\filedate}{Initial version} +% +% \GetFileInfo{lmake.dtx} +% +% \DoNotIndex{\newcommand,\newenvironment} +% \DoNotIndex{\#,\$,\%,\&,\@,\\,\{,\},\^,\_,\~,\ } +% \DoNotIndex{\def,\edef,\if,\else,\fi,\begingroup,\endgroup} +% \DoNotIndex{\@ifpackageloaded,\advance,\cdots,\csname,\endcsname} +% \DoNotIndex{\dotsb,\dotsc,\empty,\end,\expandafter,\global} +% \DoNotIndex{\i,\ifcase,\ifnum,\ifx,\or,\relax,\string,\the,\let} +% \DoNotIndex{\ldots,\newcount,\newif,\noexpand,\protected@edef} +% +% +% \title{The \texttt{lmake} package\thanks{This document +% corresponds to \texttt{lmake}~\fileversion, dated \filedate.}} +% \author{Shengjun Pan \\ \texttt{panshengjun@gmail.com}} +% \date{} +% \maketitle +% \newcommand{\bs}{\char`\\} +% \newcommand{\us}{\char`\_} +% \newcommand{\ur}{\char`\^} +% \renewcommand{\arraystretch}{1.2} +% \setlength{\fboxsep}{1ex} +% \definecolor{lightGray}{rgb}{0.85,0.85,0.85} +% \definecolor{lightBlue}{rgb}{0.75,0.75,1} +% \noindent\hspace*{-0.075\textwidth}\colorbox{lightGray}{\begin{minipage}{1.15\textwidth} +% \[ +% \lcmd{\hat}{h}{X,A,B,F,\mu,\phi,\sigma} +% \lmake[\int_{\hX_\i=\hA_\i}^{\hB_\i},\empty] +% \binom{N}{\lmake[\i\hphi_\i,,m]} +% \lmake[e^{-\frac{(\hX_\i-\hmu_\i)^2}{2\hsigma_\i^2}},c=] +% \lmake[d\hX_\i,\,] +% \] +% \tt +% \bs lcmd\{\bs hat\}\{h\}\{X,A,B,F,\bs mu,\bs phi,\bs sigma\}\\ +% \bs lmake[\bs in\us\{\bs hX\us\bs i=\bs hA\us\bs i\}\ur\{\bs hB\us\bs i\},\bs empty]\\ +% \bs binom\{N\}\{\bs lmake[\bs i\bs hphi\us\bs i,,m]\}\\ +% \bs lmake[e\ur\{-\bs frac\{(\bs hX\us\bs i-\bs hmu\us\bs i)\ur2\}\{2\bs hsigma\us\bs i\ur2\}\},c=]\\ +% \bs lmake[d\bs hX\us\bs i,\bs,] +% \end{minipage}} +% \section{Introduction} +% This package provides macros for \LaTeX2e to simplify typesetting a +% list of phrases that fit a pattern.\\ +% \begin{tabular}{ll} +% \tt \char`\\lcmd +% & makes a list of new commands by adding a prefix to existing +% commands.\\ +% \tt\char`\\lmake +% & makes a list of the form $p(i_1),p(i_2),\dotsc,p(i_n)$, where +% $p(.)$ stands for \emph{pattern}. +% \end{tabular} +% \section{Usage and examples} +% \label{sec:usage} +% \DescribeMacro{\lcmd} +% \fcolorbox{black}{lightBlue}{\tt \char`\\lcmd\{command\}\{prefix\}\{list\}}\\[2ex] +% makes a list of new commands from \texttt{command} by adding \texttt{prefix} +% to each item in the comma-separated \texttt{list}. If an item in the +% list is a macro, only its name is prefixed; the backslash is stripped away.\\[3ex] +% \textbf{Examples}: +% \footnote{The examples used in this document require packages {\tt amsmath, +% amssymb} and {\tt graphicx}.}\\[1ex] +% \lcmd{\mathcal}{c}{A,X,P} +% \lcmd{\mathbb}{bb}{Z,R,E} +% \lcmd{\overline}{vct}{x,\phi,psi} +% \begin{tabular}{l@{ defines: }lll} +% \hline +% \verb|\lcmd{\mathcal}{c}{A,X,P}| +% &\texttt{\char`\\ cA} $\to \cA$ +% &\texttt{\char`\\ cX} $\to \cX$ +% &\texttt{\char`\\ cP} $\to \cP$ +% \\ +% \verb|\lcmd{\mathbb}{c}{A,X,P}| +% &\texttt{\char`\\ bbZ} $\to \bbZ$ +% &\texttt{\char`\\ bbR} $\to \bbR$ +% &\texttt{\char`\\ bbE} $\to \bbE$\\ +% \verb|\lcmd{\overline}{vct}{x,psi,\phi}| +% &\texttt{\char`\\ vctx} $\to \vctx$ +% &\texttt{\char`\\ vctpsi} $\to \vctpsi$ +% &\texttt{\char`\\ vctphi} $\to \vctphi$\\ +% \hline +% \end{tabular}\\[2ex] +% In the last example the new command for \verb|\phi| is +% \verb|\vctphi|, not \verb|\vct\phi|. Notice the difference between +% \verb|\vctphi| and \verb|\vctpsi|.\\[4ex] +% \DescribeMacro{\lmake} +% \fcolorbox{black}{lightBlue}{\tt\bs lmake[[key1=]value1,[key2=]value2,...]}\\[2ex] +% makes a list of symbols by key-value pairs. Valid keys are +% described in the following table.\\[3ex] +% \begin{tabular}{@{\tt }rll} +% \hline +% keys & default & description\\ +% \hline +% p & \verb|\i| & Pattern. All occurrences of \verb|\i| will be replaced +% by the corresponding index.\\ +% c & \verb|,| & Separator.\\ +% n &\verb|n| & Last index.\\ +% 1 & \verb|1| & First index.\\ +% 2 & \verb|2| & Second index.\\ +% d & \verb|\ldots|, \verb|\cdots| & Dots. If the separator is comma, +% \verb|\ldots| is used; otherwise \verb|\cdots| is used.\\ +% & \verb|\dotsc|, \verb|\dotsb| & If \verb|amsmath| is loaded, +% \verb|\dotsc| and \verb|\dotsb| are used respectively.\\ +% $\ell$ & \verb|{}| & List of comma-separated symbols.\\ +% \hline +% \end{tabular}\\[3ex] +% \textbf{Examples}:\\[1ex] +% \begin{tabular}{ll} +% \hline +% what you type & what you see\\ +% \hline +% \verb|\lmake[]| & $\lmake[]$\\ +% \verb|\lmake[2=]| & $\lmake[2=]$\\ +% \verb|\lmake[x_\i,c=]| & $\lmake[x_\i,c=]$\\ +% \verb|\lmake[x_\i,,N]| & $\lmake[x_\i,,N]$\\ +% \verb|\lmake[x_\i,\ge,k]| & $\lmake[x_\i,\ge,k]$\\ +% \verb|\lmake[\bar x_{\i},\circ,1=i,i+1]| & $\lmake[\bar x_{\i},\circ,1=i,i+1]$\\ +% \verb|\lmake[p_\i^{\mu_\i},c=,m]| & $\lmake[p_\i^{\mu_\i},c=,m]$\\ +% \verb|\lmake[N_\i!,\,,\Gamma,\alpha,\beta]| & $\lmake[N_\i!,\,,\Gamma,\alpha,\beta]$\\ +% \verb|\lmake[\left(\frac{\i}{\i+1}\right),\!]| +% & $\lmake[\left(\frac{\i}{\i+1}\right),\!]$\\ +% \verb|\lmake[(e_\i+1),c=,k,1,2]| & $\lmake[(e_\i+1),c=,k,1,2]$\\[1ex] +% \verb|\lmake[x_{\i},l={1,3,5,11}]| +% & $\lmake[x_{\i},l={1,3,5,11}]$\\ +% \verb|\lmake[\rotatebox{-30}{\i},\to,l={A,B,C,D}]| +% & $\lmake[\rotatebox{-30}{\i},\to,l={A,B,C,D}]$\\ +% \hline +% \end{tabular}\\[2ex] +% \emph{Remarks:} +% \begin{itemize} +% \item If $\tt \ell$ is empty, the resulting list has the following form:\\ +% \verb|p(1) c p(2) c d c p(n)| +% +% If $\tt \ell$ is not empty, the resulting list has the +% following form, for the example $\tt \ell=\{x,y,z,u\}$:\\ +% \verb|p(x) c p(y) c p(z) c p(u)| +% \item A \underline{non-empty item without \texttt{=}} in the argument +% list is treated as a value. Normally the key-value pairs can appear +% out of order in the argument list to \verb|\lmake|. For fast typing +% the key can be omitted. The missing key is searched, starting from +% the key that would follow the previous key in the table-order. Only +% keys without values are searched. +% +% For example, in \verb|\lmake[\bar x_{\i},\circ,1=i,i+1]|, the +% missing key for \verb|\bar x_{\i}| is \verb|p|, the missing key for +% \verb|\circ| is \verb|c| since it follows \verb|p| in the +% table. Similarly, the missing key for \verb|i+1| is \verb|2| since +% it follows the previous key \verb|1| in the able. +% \item A key not appearing or skipped in the argument list takes its +% default value, unless it's been searched as a missing key and given +% a value. +% +% For example, in \verb|\lamke[x_\i,,N]|, all keys except for \verb|p| +% and \verb|n| take default values. Particularly, the key \verb|c| is +% skipped and it is treated as missing. +% +% Note that a skipped key does not take value \emph{empty}. To force a +% value to be empty, use one of the following workarounds: +% {\tt \char`\\empty}, {\tt key=}, {\tt key=\char`\\empty}, or {\tt +% key=\{\}}. +% \end{itemize} +% +% \StopEventually{} +% +% \section{Implementation} +% This section explains in details how verb|\lmake|, \verb|\lcmd| and +% necessary internal macros are implemented. +% \begin{macro}{\L@Compare} +% \verb|\L@Compare{string1}{string2}|\\ +% compares two strings. The two arguments are fully expanded before compassion. +% \verb|\ifL@Equal| is a Boolean variable for storing the result. +% \begin{macrocode} +\newif\ifL@Equal +\def\L@Compare#1#2{% + \protected@edef\L@a{#1}\protected@edef\L@b{#2}% + \ifx\L@a\L@b\L@Equaltrue\else\L@Equalfalse\fi} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\L@FuzzyCompare} +% \verb|\L@FuzzyCompare{string1}{string2}|\\ +% tests if two strings are the same, where white spaces preceding the +% second argument are ignores. This allows flexible writing of +% the comma-separated argument to \verb|\lmake| so that spaces may be inserted +% between an item and the previous comma. +% \begin{macrocode} +\def\L@FuzzyCompare#1#2{% + \L@Compare{#1}{#2}\ifL@Equal\else\L@Compare{#1}{ #2}\fi} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\L@SoftCompare} +% \verb|\L@SoftCompare{string1}{string2}|\\ +% similar to \verb|\L@Compare|, but does not expand the two +% strings. This is usefully if either argument contains undefined +% macros, for example, the value to the key \verb|p| in the argument to \verb|\lmake|. +% \begin{macrocode} +\def\L@SoftCompare#1#2{% + \def\L@a{#1}\def\L@b{#2}% + \ifx\L@a\L@b\L@Equaltrue\else\L@Equalfalse\fi} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\L@FuzzySoftCompare} +% \verb|\L@FuzzySoftCompare{string1}{string2}|\\ +% similar to \verb|L@FuzzyCompare|, but uses \verb|\L@SoftCompare| +% instead of \verb|\L@Compare|. +% \begin{macrocode} +\def\L@FuzzySoftCompare#1#2{% + \L@SoftCompare{#1}{#2}\ifL@Equal\else\L@SoftCompare{#1}{ #2}\fi} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\L@HasEqualSign} +% \verb|\L@HasEqualSign{string}|\\ +% tests if a string has an equal sign \verb|=|. This is used to test +% if an argument to \verb|\lmake| is a key-value pair or just a +% value. It is defined indirectly via \verb|\L@HES|, which is a tail +% recursion for scanning the tokens in its argument.\\[1ex] +% \verb|\L@Ignore| is an auxiliary macro that simply ignores its +% argument. The test result is stored in \verb|\ifL@HasEqualSign|. +% \begin{macrocode} +\def\L@Ignore#1\end{} +\newif\ifL@HasEqualSign +\def\L@HasEqualSign#1{% + \L@HasEqualSignfalse\L@HES#1\end} +\def\L@HES#1{% + \ifx#1=\L@HasEqualSigntrue\let\L@Next=\L@Ignore% + \else\ifx#1\end\let\L@Next=\relax\else\let\L@Next=\L@HES\fi% + \fi\L@Next} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\L@ArName} +% \verb|\L@ArName[index]|\\ +% returns the name of a macro via a numeric index. +% \begin{macrocode} +\def\L@ArName[#1]{\ifcase#1 L@Pattern\or L@Comma\or L@Last\or% +L@First\or L@Second\or L@Dots\or L@List\else L@Other\fi} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\L@Set,\L@Get} +% \verb|\L@Set[index]=value;|\\ +% \verb|\L@Get[Index]|\\ +% set and get the value of a macro by a numeric index. Numeric indices are +% used to locate missing keys in the argument to \verb|\lmake|. +% \begin{macrocode} +\def\L@Set[#1]=#2;{\global\expandafter\let\csname\L@ArName[#1]\endcsname=#2} +\def\L@Get[#1]{\csname\L@ArName[#1]\endcsname} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\L@LDots,\L@Cdots} +% denotes the default macro for low dots. If \verb|amsmath| is loaded before +% \verb|\lmake|, \verb|\L@LDots| is set to \verb|\dotsc| and +% \verb|\L@Cdots| is set to \verb|\dotsb|. Otherwise \verb|\L@LDots| +% is set to \verb|\ldots| and \verb|\L@Cdots| is set to \verb|\cdots|. +% \begin{macrocode} +\@ifpackageloaded{amsmath} + {\def\L@Ldots{\dotsc}\def\L@Cdots{\dotsb}} + {\def\L@Ldots{\ldots}\def\L@Cdots{\cdots}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\L@Map} +% \verb|\L@Map{function}{list}{new separator}|\\ +% maps a list of comma-separated items to a new list, so that each +% item is transformed using the given function, and the commas are +% replaced with the new separator. It is defined indirectly +% indirectly via \verb|\L@Iterate|, which is a tail recursion for +% scanning the comma-separated list.\\[1ex] +% \verb|\ifL@Start| is used to indicate if the current item is the +% first item, which is not preceded by a comma, unlike the remaining +% items.\\[1ex] +% \verb|\L@Map| +% \begin{macrocode} +\newif\ifL@Start +\def\L@Map#1#2#3{% + \def\L@Sym{\empty}\def\LM@Func{#1}\def\L@Sep{#3}% + \L@Starttrue\expandafter\L@Iterate#2,\end} +\def\L@Iterate#1,#2{% + \LM@Func{#1}% + \ifx#2\end\let\L@Next=\relax\def\L@Nextarg{\empty}% + \else\L@Sep\let\L@Next=\L@Iterate\def\L@Nextarg{#2}\fi% + \expandafter\L@Next\L@Nextarg} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\L@GetKeyValue} +% \verb|\L@GetKeyValue{key-value pair}|\\ +% extracts the key and value from a string, and store them in +% \verb|\L@Key| and \verb|\L@Value| respectively. If the argument has no +% equal sign, it is used as a value and the key is set to empty. Otherwise, +% \verb|\L@GetKV| is called to extract the key and value. +% \begin{macrocode} +\def\L@GetKeyValue#1{% + \def\L@Key{}\def\L@Value{}\L@HasEqualSign{#1}% + \ifL@HasEqualSign\L@GetKV#1\end% + \else\def\L@Key{}\def\L@Value{#1}% + \fi} +\def\L@GetKV#1=#2\end{% + \def\L@Key{#1}\def\L@Value{#2}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\L@Parse} +% \verb|\L@Parse{list}|\\ +% parses a list of comma-separated items, extracts each item, +% extract its key and value, looks for keys \verb|p|, \verb|c|, +% \verb|n|, \verb|1|, \verb|2|, \verb|d| and \verb|l|, and finally assigns the +% corresponding values to \verb|\L@Pattern|, \verb|\L@Comma|, +% \verb|\L@Last|, \verb|\L@First|, \verb|\l@Second|, \verb|\L@Dots| +% and \verb|\L@List| respectively.\\[1ex] +% The counter \verb|\L@idx| is the index of the next key yet to be assigned +% with an value. +% \begin{macrocode} +\newcount\L@idx +% \end{macrocode} +% If the list is not empty, then it calls a tail recursion \verb|\l@PRS|. +% \begin{macrocode} +\def\L@Parse#1{\L@idx=0% + \L@FuzzySoftCompare{#1}{}% + \ifL@Equal\else\def\L@Extra{}\L@PRS#1,\end,\fi} +% \end{macrocode} +% An artificial item \verb|,\end,| +% is added to the end of the actual list, which terminates the +% recursion when encountered. +% \begin{macrocode} +\def\L@PRS#1,{% + \L@SoftCompare{#1}{\end}\ifL@Equal% + \let\L@Next=\relax% + \else% +% \end{macrocode} +% If an item is empty, the missing key is searched and +% the corresponding default value is used. +% \begin{macrocode} + \L@FuzzySoftCompare{#1}{}\ifL@Equal% + \ifnum\L@idx<7% + \ifcase\the\L@idx% + \def\L@Default{\i}% + \or\def\L@Default{,}% + \or\def\L@Default{n}% + \or\def\L@Default{1}% + \or\def\L@Default{2}% + \or\def\L@Default{}% + \or\def\L@Default{}% + \fi% + \L@Set[\the\L@idx]=\L@Default;% + \advance \L@idx by 1% + \fi% +% \end{macrocode} +% If the item is not empty, the key and value are extracted. Depending +% on what the key is, the value is assigned to the approximate macro. +% \begin{macrocode} + \else% + \L@GetKeyValue{#1}\let\L@CV=\L@Value% + \L@FuzzyCompare{\L@Key}{p}\ifL@Equal\L@idx=1\L@Set[0]=\L@CV;% + \else\L@FuzzyCompare{\L@Key}{c}\ifL@Equal\L@idx=2\L@Set[1]=\L@CV;% + \else\L@FuzzyCompare{\L@Key}{n}\ifL@Equal\L@idx=3\L@Set[2]=\L@CV;% + \else\L@FuzzyCompare{\L@Key}{1}\ifL@Equal\L@idx=4\L@Set[3]=\L@CV;% + \else\L@FuzzyCompare{\L@Key}{2}\ifL@Equal\L@idx=5\L@Set[4]=\L@CV;% + \else\L@FuzzyCompare{\L@Key}{d}\ifL@Equal\L@idx=6\L@Set[5]=\L@CV;% + \else\L@FuzzyCompare{\L@Key}{l}\ifL@Equal\L@idx=7\L@Set[6]=\L@CV;% +% \end{macrocode} +% If an item is a value without a key, the missing key is searched and +% given the current value. +% \begin{macrocode} + \else\L@FuzzyCompare{\L@Key}{}\ifL@Equal% + \ifnum\L@idx<7% + \L@Set[\the\L@idx]=\L@CV;% + \fi% + \advance \L@idx by 1% + \fi\fi\fi\fi\fi\fi\fi\fi\fi% + \let\L@Next=\L@PRS% + \fi% + \L@Next} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\lmake} +% \verb|\lmake[key-value list]|\\ +% makes a list of symbols using the given key-value +% pairs. \verb|\ifL@FoundFirst| is used to indicate if the first +% non-empty symbol is encountered; the first symbol is not preceded +% by a separator. +% \begin{macrocode} +\newif\ifL@FoundFirst +% \end{macrocode} +% \verb|\L@Parse| is used twice. The first time it is used to set the +% default values. The second time it is used to set the values +% supplied by the argument list. +% \begin{macrocode} +\newcommand{\lmake}[1][]{% +\begingroup% + \L@Parse{p=\i,c={,},d=,1=1,2=2,n=n,l=}% + \L@Parse{#1}% +% \end{macrocode} +% The pattern is used to define the transforming function +% \verb|\L@Func| by replacing all occurrences of \verb|\i| by the +% actual argument. +% \begin{macrocode} + \def\L@Func##1{\def\i{##1}\L@Get[0]}% +% \end{macrocode} +% If the key \verb|d| is not given a value, its value is automatically determined by +% the value of the separator. +% \begin{macrocode} + \L@Compare{\L@Dots}{\empty}\ifL@Equal% + \L@Compare{\L@Comma}{,}\ifL@Equal% + \def\L@Dots{\L@Ldots}\else\def\L@Dots{\L@Cdots}% + \fi + \fi +% \end{macrocode} +% The last step is to typeset the list of symbols. If the value to the key $\ell$ is +% missing, the typeset list starts with two symbols followed by the dots and +% ends with the last symbol. The symbols and dots are separated by the +% separator. +% \begin{macrocode} + \L@Compare{\L@List}{\empty}\ifL@Equal% + \L@FoundFirstfalse% + \L@Compare{\L@First}{\empty}\ifL@Equal\else% + \L@Func{\L@First}\L@FoundFirsttrue% + \fi% + \L@Compare{\L@Second}{\empty}\ifL@Equal\else% + \ifL@FoundFirst\L@Comma\fi% + \L@Func{\L@Second}\L@FoundFirsttrue% + \fi% + \L@Compare{\L@Dots}{\empty}\ifL@Equal\else% + \ifL@FoundFirst\L@Comma\fi\L@Dots% + \fi% + \L@Compare{\L@Last}{\empty}\ifL@Equal\else% + \L@Comma\L@Func{\L@Last}% + \fi% +% \end{macrocode} +% If a non-empty value to the key $\ell$ is given, the typeset list +% consists of symbols from the items in the value of $\ell$, +% transformed by the pattern function. +% \begin{macrocode} + \else% + \L@Map{\L@Func}{\L@List}{\L@Comma}% + \fi% +\endgroup} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\L@CmdName} +% \verb|\L@CmdName{string}|\\ +% returns the string itself if it is not a macro, otherwise returns +% the macro name with the backslash stripped away. This is an +% auxiliary function to \verb|\lcmd|. +% \begin{macrocode} +\def\L@CmdName#1{% + \if\noexpand#1\noexpand\L@anycmd\expandafter\L@StripFirst\string#1\else#1\fi} +\def\L@StripFirst#1#2{#2} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\lcmd} +% \verb|\lcmd{command}{prefix}{list}|\\ +% makes a list of new commands. See Section~\ref{sec:usage} for more details. +% \begin{macrocode} +\def\lcmd#1#2#3{% + \def\L@MakeCmd##1{% + \expandafter\def\csname #2\L@CmdName##1\endcsname{#1{##1}}}% + \L@Map{\L@MakeCmd}{#3}{}} +% \end{macrocode} +% \end{macro} +% \Finale +\endinput + diff --git a/macros/latex/contrib/lmake/lmake.ins b/macros/latex/contrib/lmake/lmake.ins new file mode 100644 index 0000000000..0bdf22092c --- /dev/null +++ b/macros/latex/contrib/lmake/lmake.ins @@ -0,0 +1,55 @@ +%% +%% Copyright (C) 2012 by Shengjun Pan +%% +%% This file may be distributed and/or modified under the conditions of +%% the LaTeX Project Public License, either version 1.2 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.2 or later is part of all distributions of LaTeX version +%% 1999/12/01 or later. +%% + +\input docstrip.tex +\keepsilent + +\usedir{tex/latex/lmake} + +\preamble + +This is a generated file. + +Copyright (C) 2012 by Shengjun Pan + +This file may be distributed and/or modified under the conditions of +the LaTeX Project Public License, either version 1.2 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.2 or later is part of all distributions of LaTeX version +1999/12/01 or later. + +\endpreamble + +\generate{\file{lmake.sty}{\from{lmake.dtx}{package}}} + +\obeyspaces +\Msg{*************************************************************} +\Msg{* *} +\Msg{* To finish the installation you have to move the following *} +\Msg{* file into a directory searched by TeX: *} +\Msg{* *} +\Msg{* lmake.sty *} +\Msg{* *} +\Msg{* To produce the documentation run the file lmake.dtx *} +\Msg{* through LaTeX. *} +\Msg{* *} +\Msg{* Happy TeXing! *} +\Msg{* *} +\Msg{*************************************************************} + +\endbatchfile diff --git a/macros/latex/contrib/lmake/lmake.pdf b/macros/latex/contrib/lmake/lmake.pdf new file mode 100644 index 0000000000..0b588f6ce1 Binary files /dev/null and b/macros/latex/contrib/lmake/lmake.pdf differ diff --git a/macros/latex/contrib/lmake/lmake.sty b/macros/latex/contrib/lmake/lmake.sty new file mode 100644 index 0000000000..50a4c76126 --- /dev/null +++ b/macros/latex/contrib/lmake/lmake.sty @@ -0,0 +1,147 @@ +%% +%% This is file `lmake.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% lmake.dtx (with options: `package') +%% +%% This is a generated file. +%% +%% Copyright (C) 2012 by Shengjun Pan +%% +%% This file may be distributed and/or modified under the conditions of +%% the LaTeX Project Public License, either version 1.2 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.2 or later is part of all distributions of LaTeX version +%% 1999/12/01 or later. +%% +\NeedsTeXFormat{LaTeX2e}[1999/12/01] +\ProvidesPackage{lmake} + [2012/02/29 v1.0 .dtx lmake file] +\newif\ifL@Equal +\def\L@Compare#1#2{% + \protected@edef\L@a{#1}\protected@edef\L@b{#2}% + \ifx\L@a\L@b\L@Equaltrue\else\L@Equalfalse\fi} +\def\L@FuzzyCompare#1#2{% + \L@Compare{#1}{#2}\ifL@Equal\else\L@Compare{#1}{ #2}\fi} +\def\L@SoftCompare#1#2{% + \def\L@a{#1}\def\L@b{#2}% + \ifx\L@a\L@b\L@Equaltrue\else\L@Equalfalse\fi} +\def\L@FuzzySoftCompare#1#2{% + \L@SoftCompare{#1}{#2}\ifL@Equal\else\L@SoftCompare{#1}{ #2}\fi} +\def\L@Ignore#1\end{} +\newif\ifL@HasEqualSign +\def\L@HasEqualSign#1{% + \L@HasEqualSignfalse\L@HES#1\end} +\def\L@HES#1{% + \ifx#1=\L@HasEqualSigntrue\let\L@Next=\L@Ignore% + \else\ifx#1\end\let\L@Next=\relax\else\let\L@Next=\L@HES\fi% + \fi\L@Next} +\def\L@ArName[#1]{\ifcase#1 L@Pattern\or L@Comma\or L@Last\or% +L@First\or L@Second\or L@Dots\or L@List\else L@Other\fi} +\def\L@Set[#1]=#2;{\global\expandafter\let\csname\L@ArName[#1]\endcsname=#2} +\def\L@Get[#1]{\csname\L@ArName[#1]\endcsname} +\@ifpackageloaded{amsmath} + {\def\L@Ldots{\dotsc}\def\L@Cdots{\dotsb}} + {\def\L@Ldots{\ldots}\def\L@Cdots{\cdots}} +\newif\ifL@Start +\def\L@Map#1#2#3{% + \def\L@Sym{\empty}\def\LM@Func{#1}\def\L@Sep{#3}% + \L@Starttrue\expandafter\L@Iterate#2,\end} +\def\L@Iterate#1,#2{% + \LM@Func{#1}% + \ifx#2\end\let\L@Next=\relax\def\L@Nextarg{\empty}% + \else\L@Sep\let\L@Next=\L@Iterate\def\L@Nextarg{#2}\fi% + \expandafter\L@Next\L@Nextarg} +\def\L@GetKeyValue#1{% + \def\L@Key{}\def\L@Value{}\L@HasEqualSign{#1}% + \ifL@HasEqualSign\L@GetKV#1\end% + \else\def\L@Key{}\def\L@Value{#1}% + \fi} +\def\L@GetKV#1=#2\end{% + \def\L@Key{#1}\def\L@Value{#2}} +\newcount\L@idx +\def\L@Parse#1{\L@idx=0% + \L@FuzzySoftCompare{#1}{}% + \ifL@Equal\else\def\L@Extra{}\L@PRS#1,\end,\fi} +\def\L@PRS#1,{% + \L@SoftCompare{#1}{\end}\ifL@Equal% + \let\L@Next=\relax% + \else% + \L@FuzzySoftCompare{#1}{}\ifL@Equal% + \ifnum\L@idx<7% + \ifcase\the\L@idx% + \def\L@Default{\i}% + \or\def\L@Default{,}% + \or\def\L@Default{n}% + \or\def\L@Default{1}% + \or\def\L@Default{2}% + \or\def\L@Default{}% + \or\def\L@Default{}% + \fi% + \L@Set[\the\L@idx]=\L@Default;% + \advance \L@idx by 1% + \fi% + \else% + \L@GetKeyValue{#1}\let\L@CV=\L@Value% + \L@FuzzyCompare{\L@Key}{p}\ifL@Equal\L@idx=1\L@Set[0]=\L@CV;% + \else\L@FuzzyCompare{\L@Key}{c}\ifL@Equal\L@idx=2\L@Set[1]=\L@CV;% + \else\L@FuzzyCompare{\L@Key}{n}\ifL@Equal\L@idx=3\L@Set[2]=\L@CV;% + \else\L@FuzzyCompare{\L@Key}{1}\ifL@Equal\L@idx=4\L@Set[3]=\L@CV;% + \else\L@FuzzyCompare{\L@Key}{2}\ifL@Equal\L@idx=5\L@Set[4]=\L@CV;% + \else\L@FuzzyCompare{\L@Key}{d}\ifL@Equal\L@idx=6\L@Set[5]=\L@CV;% + \else\L@FuzzyCompare{\L@Key}{l}\ifL@Equal\L@idx=7\L@Set[6]=\L@CV;% + \else\L@FuzzyCompare{\L@Key}{}\ifL@Equal% + \ifnum\L@idx<7% + \L@Set[\the\L@idx]=\L@CV;% + \fi% + \advance \L@idx by 1% + \fi\fi\fi\fi\fi\fi\fi\fi\fi% + \let\L@Next=\L@PRS% + \fi% + \L@Next} +\newif\ifL@FoundFirst +\newcommand{\lmake}[1][]{% +\begingroup% + \L@Parse{p=\i,c={,},d=,1=1,2=2,n=n,l=}% + \L@Parse{#1}% + \def\L@Func##1{\def\i{##1}\L@Get[0]}% + \L@Compare{\L@Dots}{\empty}\ifL@Equal% + \L@Compare{\L@Comma}{,}\ifL@Equal% + \def\L@Dots{\L@Ldots}\else\def\L@Dots{\L@Cdots}% + \fi + \fi + \L@Compare{\L@List}{\empty}\ifL@Equal% + \L@FoundFirstfalse% + \L@Compare{\L@First}{\empty}\ifL@Equal\else% + \L@Func{\L@First}\L@FoundFirsttrue% + \fi% + \L@Compare{\L@Second}{\empty}\ifL@Equal\else% + \ifL@FoundFirst\L@Comma\fi% + \L@Func{\L@Second}\L@FoundFirsttrue% + \fi% + \L@Compare{\L@Dots}{\empty}\ifL@Equal\else% + \ifL@FoundFirst\L@Comma\fi\L@Dots% + \fi% + \L@Compare{\L@Last}{\empty}\ifL@Equal\else% + \L@Comma\L@Func{\L@Last}% + \fi% + \else% + \L@Map{\L@Func}{\L@List}{\L@Comma}% + \fi% +\endgroup} +\def\L@CmdName#1{% + \if\noexpand#1\noexpand\L@anycmd\expandafter\L@StripFirst\string#1\else#1\fi} +\def\L@StripFirst#1#2{#2} +\def\lcmd#1#2#3{% + \def\L@MakeCmd##1{% + \expandafter\def\csname #2\L@CmdName##1\endcsname{#1{##1}}}% + \L@Map{\L@MakeCmd}{#3}{}} +\endinput +%% +%% End of file `lmake.sty'. -- cgit v1.2.3