% \iffalse meta-comment %<=*COPYRIGHT> %% Copyright (C) 2012 by Martin Scharrer %% -------------------------------------------------------------------- %% 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 `maintained'. %% %% The Current Maintainer of this work is Martin Scharrer. %% %% This work consists of the files multienv.dtx and multienv.ins %% and the derived filebase multienv.sty. %% %<=/COPYRIGHT> % \fi % % \iffalse %<*driver> \ProvidesFile{multienv.dtx}[% %<=*DATE> 2012/05/20 %<=/DATE> %<=*VERSION> v1.0 %<=/VERSION> DTX file for multienv.sty] \documentclass{ydoc} \GetFileInfo{multienv.dtx} \usepackage{multienv}[\filedate] \providecommand\enquote[1]{``#1''} \EnableCrossrefs \CodelineIndex \RecordChanges \OnlyDescription \optionaloff \begin{document} \DocInput{\jobname.dtx} \PrintChanges \PrintIndex \end{document} % % \fi % % \CheckSum{297} % % \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}{2012/05/20}{First release.} % % \DoNotIndex{\newcommand,\newenvironment} % % \GetFileInfo{multienv.dtx} % \author{Martin Scharrer} % \email{martin@scharrer-scharrer.de} % \ifdefined\repository % \repository{https://bitbucket.org/martin_scharrer/multienv} % \fi % % \maketitle % % \begin{abstract}\noindent % This package provides a \env{multienv} environment which allows to % easily add multiple environments using a key=value syntax. % Macros to define environments using this syntax are also provided. % \end{abstract} % % \section{Introduction} % It is sometimes required to add multiple environments around some text % in order to achieve a specific format. This macro simplifies this task % especially for larger number of environments by allowing the environments % and their arguments to be specified using a key=value syntax. % A special \Key{add code} key is also provided to allow arbitrary code being % added before and after the environment content. % Furthermore macros are provided to allow the definition of new environments % which contain multiple other environments and code. % % \section{Usage} % \vspace{-3ex} % \DescribeEnv[]{multienv}{',',\ldots} % This environment takes a comma separated list of key=values where the keys are usually environment % names and the values the arguments to this environment. % The environments are added around the content in the given order, i.e.\ the first environment % is the most outer one and further environments are placed inside it. % % At the moment only the following key is defined. Any other key is taken as an environment name. % % \DescribeKey{add code}={}{} % This adds the given code before and after the content. % Any code is permitted including macro argument tokens like `|#1|'. % % \DescribeKey{\meta{environment}} % \DescribeKey{\meta{environment}}= % Any unknown key is taken as environment name and the value as argument(s) to the environment. % If the value does not start with a brace `|{|', bracket `|[|' or angle `|<|' it is taken % as a single mandatory argument and is placed inside braces after the environment, % otherwise it is placed unchanged after the environment: % \par\medskip\par\noindent % \begin{tabular}{@{}l@{ $\Rightarrow$ }l@{}} % \Key{\meta{env}} & \Macro\begin{}\ldots\Macro\end{} \\ % \Key{\meta{env}}= & \Macro\begin{}\ldots\Macro\end{} \\ % \Key{\meta{env}}= & \Macro\begin{}{}\ldots\Macro\end{} \\ % \Key{\meta{env}}={} & \Macro\begin{}{}\ldots\Macro\end{} \\ % \Key{\meta{env}}={}{} & \Macro\begin{}{}{}\ldots\Macro\end{} \\ % \Key{\meta{env}}=[] & \Macro\begin{}[]\ldots\Macro\end{} \\ % \Key{\meta{env}}=[]{} & \Macro\begin{}[]{}\ldots\Macro\end{} \\ % \Key{\meta{env}}=<< >> & \Macro\begin{}<< >>\ldots\Macro\end{} \\ % \Key{\meta{env}}=<< >>{} & \Macro\begin{}<< >>{}\ldots\Macro\end{} \\ % \multicolumn{2}{@{}l@{}}{etc.} \\ % \end{tabular} % \par\bigskip\par % % \DescribeEnv[]{multienv*}{',',\ldots} % This environment is identical to \env{multienv} but will apply the keys in the reverse order, % i.e.\ every environment or code is added around the existing environments or code. % % % \DescribeMacro\newmultienvironment{}[][]{,\ldots} % This macro defines a new environment like \Macro\newenvironment does but uses the \env{multienv} % syntax. The resulting environment will contain all given environments and code. % The environment can have arguments including one leading optional argument. % The arguments can be used as part of the keys and values. % It should be noted that it is not allowed to use arguments in the second argument of % the \Key{add code} key, because that code will be part of \Macro\end{}. % % An error is raised if the environment already exists. % % \DescribeMacro\renewmultienvironment{}[][]{,\ldots} % Like \Macro\newmultienvironment but can be used to redefine existing environments. % It is is not relevant \emph{how} the environment was defined previously. % An error is raised if the environment does not already exist. % % % \DescribeMacro\providemultienvironment{}[][]{,\ldots} % Like \Macro\newmultienvironment but the environment is only defined if it is not already defined. % The environment is also not defined if there a macro with the same name exists. % % \section{Examples} % \lstset{gobble=4,language=[latex]tex} % The following \env{multienv} environment usage: % \begin{lstlisting} % \begin{multienv}{enva,envb=arg,add code={code before}{code after}, % envc=[oarg]{marg}} % content % \end{multienv} % \end{lstlisting} % \noindent is basically identical to: % \begin{lstlisting} % \begin{enva} % \begin{envb}{arg} % code before % \begin{enc}[oarg]{marg} % content % \end{enc} % code after % \end{envb} % \end{enva} % \end{lstlisting} % \noindent Using \env{multienv*} the order the environments can be given in the opposite order: % \begin{lstlisting} % \begin{multienv}{envc=[oarg]{marg},add code={code before}{code after}, % envb=arg,enva} % content % \end{multienv} % \end{lstlisting} % % \par\bigskip\par\noindent % The following code defines a \env{centeredminipage} environment which content is placed % in a centered \env{minipage} which inner content is also centered. % \begin{lstlisting} % \newmultienvironment{centeredminipage}[1] % {center,minipage=#1,add code={\centering}{}} % \end{lstlisting} % \par\noindent % This is basically identical to:\par % \begin{lstlisting} % \newenvironment{centeredminipage}[1] % {\begin{center}\begin{minipage}{#1}\centering} % {\end{minipage}\end{center}} % \end{lstlisting} % \par\noindent % However actually the \enquote{plain} form of the environment are used, because it is more efficient % and will also produce a correct error message if an incorrect \cs{end} macro is found:\par % \begin{lstlisting} % \newenvironment{centeredminipage}[1] % {\begingroup\center\begingroup\minipage{#1}\centering} % {\endminipage\endgroup\endcenter\endgroup} % \end{lstlisting} % \par\noindent % The groups are added because some environments require to be placed in a group by themselves, % which is normally done by |\begin| and |\end|. % % \StopEventually{} % \clearpage % \section{Implementation} % % \iffalse %<*multienv.sty> % \fi % \begin{macrocode} % \NeedsTeXFormat{LaTeX2e}[1999/12/01] \ProvidesPackage{multienv}[% % % %<*DRIVER> 2099/01/01 develop % Add multiple environments using a Key=value syntax] % \end{macrocode} % % % \begin{macro}{\multienv} % \begin{macrocode} \newcommand{\multienv}{% \begingroup \@ifstar{% \let\multienv@addcode\multienv@addcode@out \multienv@readkeys }{% \let\multienv@addcode\multienv@addcode@in \multienv@readkeys }% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\endmultienv} % \begin{macrocode} \def\endmultienv{\end@multienv\endgroup} % \end{macrocode} % \end{macro} % % % \begin{environment}{multienv*} % \begin{macrocode} \newenvironment{multienv*}{% \begingroup \let\multienv@addcode\multienv@addcode@out \multienv@readkeys }{% \end@multienv\endgroup } % \end{macrocode} % \end{environment} % % % \begin{macro}{\newmultienvironment} % \begin{macrocode} \newcommand\newmultienvironment{% \let\@multi@environment\newenvironment \@multienvironment } % \end{macrocode} % \end{macro} % % % \begin{macro}{\renewmultienvironment} % \begin{macrocode} \newcommand\renewmultienvironment{% \let\@multi@environment\renewenvironment \@multienvironment } % \end{macrocode} % \end{macro} % % % \begin{macro}{\providemultienvironment} % \begin{macrocode} \newcommand\providemultienvironment{% \@ifstar {\@providemultienvironment*}% {\@providemultienvironment{}}% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\@providemultienvironment} % \begin{macrocode} \def\@providemultienvironment#1#2{% \@ifundefined{#2}% {\newmultienvironment#1{#2}}% {\begingroup\tracingall\renewcommand\@tempa[1][]{\renewcommand\@tempa[1][]{\expandafter\endgroup\@gobble}\@tempa}\@tempa}% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\@multienvironment} % \begin{macrocode} \def\@multienvironment{% \@ifstar{% \let\multienv@addcode\multienv@addcode@out \newmultienvironment@marg }{% \let\multienv@addcode\multienv@addcode@in \newmultienvironment@marg }% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\newmultienvironment@marg} % \begin{macrocode} \long\def\newmultienvironment@marg#1{% \@testopt{\newmultienvironment@oarg{#1}}{[0]}% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\newmultienvironment@oarg} % \begin{macrocode} \long\def\newmultienvironment@oarg#1[#2]{% \@ifnextchar[{% \newmultienvironment@oargb{#1}{#2}% }{% \newmultienvironment@def{#1}{[#2]}% }% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\newmultienvironment@oargb} % \begin{macrocode} \long\def\newmultienvironment@oargb#1#2[#3]{% \newmultienvironment@def{#1}{[#2][#3]}% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\newmultienvironment@def} % \begin{macrocode} \long\def\newmultienvironment@def#1#2#3{% \begingroup \multienv@readkeys@{#3}% \def\@tempa{\@multi@environment*{#1}#2}% \@temptokena\expandafter\expandafter\expandafter{\expandafter\expandafter\expandafter{\expandafter\begin@multienv\expandafter}\expandafter{\end@multienv}}% \expandafter\expandafter\expandafter \endgroup \expandafter\@tempa\the\@temptokena } % \end{macrocode} % \end{macro} % % % \begin{macro}{\multienv@readkeys} % \begin{macrocode} \long\def\multienv@readkeys#1{% \multienv@readkeys@{#1}% \begin@multienv } % \end{macrocode} % \end{macro} % % % \begin{macro}{\multienv@readkeys@} % \begin{macrocode} \long\def\multienv@readkeys@#1{% \let\begin@multienv\@empty \let\end@multienv\@empty \multienv@readkeyval#1,\@nnil,\@nnil } % \end{macrocode} % \end{macro} % % \begin{macrocode} \let\begin@multienv\@empty \let\end@multienv\@empty % \end{macrocode} % % \begin{macro}{\multienv@readkeyval} % \begin{macrocode} \long\def\multienv@readkeyval#1,{% \ifx\@nnil#1\relax \expandafter\@gobble \else \multienv@sepkeyval#1=\@nnil=\@nnil\relax \expandafter\multienv@readkeyval \fi } % \end{macrocode} % \end{macro} % % % \begin{macro}{\multienv@sepkeyval} % \begin{macrocode} \long\def\multienv@sepkeyval#1=#2={% \ifx\@nnil#2\relax \multienv@handlekeyval{#1}{}% \expandafter\@gobble \else \multienv@handlekeyval{#1}{#2}% \expandafter \@gobblefour \fi } % \end{macrocode} % \end{macro} % % % \begin{macro}{\multienv@handlekeyval} % \begin{macrocode} \long\def\multienv@handlekeyval#1#2{% \@ifundefined{multienv@key@#1}{% \multienv@addenv{#1}{#2}% }{% \@nameuse{multienv@key@#1}#2\@nnil }% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\multienv@addenv} % \begin{macrocode} \long\def\multienv@addenv#1#2{% \@ifnextchar\bgroup{% \multienv@@addenv }{% \ifcase0% \expandafter\ifx\csname @let@token\endcsname\@nnil1\else \expandafter\ifx\csname @let@token\endcsname[1\else \expandafter\ifx\csname @let@token\endcsname<1\fi\fi\fi \relax \expandafter\multienv@@addenv@ \else \expandafter\multienv@@addenv \fi }#2\@nnil{#1}% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\multienv@@addenv@} % \begin{macrocode} \long\def\multienv@@addenv@#1\@nnil{% \multienv@@addenv{{#1}}\@nnil } % \end{macrocode} % \end{macro} % % % \begin{macro}{\multienv@@addenv} % \begin{macrocode} \long\def\multienv@@addenv#1\@nnil#2{% \multienv@addcode{\multi@env{#2}#1}{\endmulti@env{#2}}% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\multi@env} % \begin{macrocode} \long\def\multi@env#1{% \begingroup \@ifundefined{#1}% {\@latex@error{Environment #1 undefined}\@eha}% {\csname #1\endcsname}% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\endmulti@env} % \begin{macrocode} \def\endmulti@env#1{\csname end#1\endcsname\endgroup} % \end{macrocode} % \end{macro} % % % \begin{macro}{\multienv@addcode@out} % \begin{macrocode} \long\def\multienv@addcode@out#1#2{% \@temptokena{#1}% \@temptokena\expandafter\expandafter\expandafter{\expandafter\the\expandafter\@temptokena\begin@multienv}% \edef\begin@multienv{\the\@temptokena}% \@temptokena\expandafter{\end@multienv#2}% \edef\end@multienv{\the\@temptokena}% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\multienv@addcode@in} % \begin{macrocode} \long\def\multienv@addcode@in#1#2{% \@temptokena\expandafter{\begin@multienv#1}% \edef\begin@multienv{\the\@temptokena}% \@temptokena{#2}% \@temptokena\expandafter\expandafter\expandafter{\expandafter\the\expandafter\@temptokena\end@multienv}% \edef\end@multienv{\the\@temptokena}% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\multienv@key@add} % \begin{macrocode} \long\@namedef{multienv@key@add code}#1\@nnil{% % \end{macrocode} % \end{macro} % % \begin{macrocode} \multienv@addcode#1{}{}% } % \end{macrocode} % % \begin{macro}{\multienv@key@adjustbox} % \begin{macrocode} \long\@namedef{multienv@key@adjustbox}#1\@nnil{% \multienv@addcode{\csname adjustbox@noindent\endcsname\adjustbox{#1}\bgroup\ignorespaces}{\ifhmode\unskip\fi\egroup}% } % \end{macrocode} % \end{macro} % % \iffalse % % \fi % % \Finale \endinput