Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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?

share|improve this question
1  
Related Question: Defining mdframe style by reference to another style. –  Peter Grill Mar 31 at 21:40

2 Answers 2

up vote 17 down vote accepted

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.

share|improve this answer
    
This is great, exactly what I was looking for. –  Christopher A. Wong Mar 31 at 6:57

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}
share|improve this answer
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 at 2:13

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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