17

I currently have several environments from mdframed that have a large number of options that are shared between them. The situation looks like

\newmdtheoremenv[options0,options1]{env1}{Environment 1}
\newmdtheoremenv[options0,options2]{env2}{Environment 2}
\newmdtheoremenv[options0,options3]{env3}{Environment 3}

etc., where in place of options0, etc, there are a long list of various options like backgroundcolor=red!1, leftmargin=0.5in, etc. I would prefer not to write out all the arguments in options0 repeatedly for each of these environments, and I was wondering if I could use a macro to do this. I tried

\newcommand{\myopts}{options0}
\newmdtheoremenv[\myopts,options1]{env1}{Environment 1}
\newmdtheoremenv[\myopts,options2]{env2}{Environment 2}
\newmdtheoremenv[\myopts,options3]{env3}{Environment 3}

but it did not work, telling me that there is a Package kvsetkeys error. Any suggestions?

17

This is a good thing, since it promotes consistency. However, your key-value argument needs to be expanded before it can be properly assigned using key-value pairs. For this you have at least two options:

  1. Explicitly insert \expandafters to jump over the construction until you reach the optional argument(s):

    \expandafter\newmdtheoremenv\expandafter[\myopts]{theorem}{Theorem}
    
  2. Implicitly expand the contents using

    \begingroup\edef\x{\endgroup%
      \noexpand\newmdtheoremenv[\myopts]{theorem}{Theorem}}\x
    

    The above magic defines \x as an expansion of everything but \newmdtheoremenv (including \endgroup). That is, only \myopts is expanded. If we assume that \myopts was defined using

    \newcommand{\myopts}{
       outerlinewidth  = 2             ,%
       roundcorner     = 10pt          ,%
       leftmargin      = 40            ,%
       rightmargin     = 40            ,%
       backgroundcolor = yellow!40     ,%
       outerlinecolor  = blue!70!black ,% 
       innertopmargin  = \topskip      ,%
       splittopskip    = \topskip       %
    }
    

    Then, after defining \x (using \edef), \x resembles (taken from the terminal):

    \endgroup \newmdtheoremenv [ outerlinewidth = 2 ,roundcorner = 10pt ,leftmarg
    in = 40 ,rightmargin = 40 ,backgroundcolor = yellow!40 ,outerlinecolor = blue!7
    0!black ,innertopmargin = \topskip ,splittopskip = \topskip ]{theorem}{Theorem
    }
    

    This is exactly what you're after.

6

While Werner answers the question posted, I would recommend an approach that uses mdfdefinestyle instead when talking about options specifically for the mdframed environment.

Define each of the collection of styles in an\mdfdefinestyle, and then combine them as desired:

\newmdtheoremenv[style=myopts,style=options1]{env1}{Environment 1}
\newmdtheoremenv[style=myopts,style=options2]{env2}{Environment 2}
\newmdtheoremenv[style=myopts,style=options3]{env3}{Environment 3}

enter image description here

Code:

\documentclass{article}
\usepackage{xcolor}
\usepackage[framemethod=tikz]{mdframed}

\mdfdefinestyle{myopts}{%
   outerlinewidth  = 2             ,%
   roundcorner     = 10pt          ,%
   leftmargin      = 40            ,%
   rightmargin     = 40            ,%
   outerlinecolor  = blue!70!black ,% 
   innertopmargin  = \topskip      ,%
   splittopskip    = \topskip       %
}

\mdfdefinestyle{options1}{%
   backgroundcolor = yellow!40,
}

\mdfdefinestyle{options2}{
   backgroundcolor = blue!20,
   frametitlerulecolor=blue,
   roundcorner=0pt,
}

\mdfdefinestyle{options3}{%
   backgroundcolor = red!20,
   frametitle={Options 3 Title},
   frametitlebackgroundcolor=olive!40,
   frametitlerule=true,       
   roundcorner=4pt,
}


\newcommand{\myopts}{options0}
\newmdtheoremenv[style=myopts,style=options1]{env1}{Environment 1}
\newmdtheoremenv[style=myopts,style=options2]{env2}{Environment 2}
\newmdtheoremenv[style=myopts,style=options3]{env3}{Environment 3}

\begin{document}

\begin{env1}
    This is \textbf{env1}.
\end{env1}

\begin{env2}
    This is \textbf{env2}.
\end{env2}

\begin{env3}
    This is \textbf{env3}.
\end{env3}

\end{document}
  • 2
    I like this solution. At least for the specific case of mdframed, it is cleaner than the other solution. Thanks. – Christopher A. Wong Apr 1 '14 at 2:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.