如何将 TikZ 绘制的 `mdframed` 框的自定义定义放入“宏”中以供重复使用?

如何将 TikZ 绘制的 `mdframed` 框的自定义定义放入“宏”中以供重复使用?

考虑以下最小工作示例:

\documentclass{article}

\usepackage[framemethod=TikZ]{mdframed} % noteboxes, boxes, etc.

\newcounter{definition}
\newenvironment{definition}[1][]{%
\stepcounter{definition}%
\ifstrempty{#1}%
{\mdfsetup{%
        frametitle={%
            \tikz[baseline=(current bounding box.east),outer sep=0pt]
            \node[anchor=east,rectangle,fill=white]
            {\strut Definition~\thedefinition};}}
}%
{\mdfsetup{%
        frametitle={%
            \tikz[baseline=(current bounding box.east),outer sep=0pt]
            \node[anchor=east,rectangle,fill=white]
            {\strut Definition~\thedefinition:~#1};}}%
}%
\mdfsetup{innertopmargin=1pt,linecolor=red!60,%
    linewidth=2pt,topline=true,
    frametitleaboveskip=\dimexpr-\ht\strutbox\relax,}
\begin{mdframed}[]\relax%
}{\end{mdframed}}

\newcounter{theorem}
\newenvironment{theorem}[1][]{%
\stepcounter{theorem}%
\ifstrempty{#1}%
{\mdfsetup{%
        frametitle={%
            \tikz[baseline=(current bounding box.east),outer sep=0pt]
            \node[anchor=east,rectangle,fill=white]
            {\strut Theorem~\thetheorem};}}
}%
{\mdfsetup{%
        frametitle={%
            \tikz[baseline=(current bounding box.east),outer sep=0pt]
            \node[anchor=east,rectangle,fill=white]
            {\strut Theorem~\thetheorem:~#1};}}%
}%
\mdfsetup{innertopmargin=1pt,linecolor=black!60,%
    linewidth=2pt,topline=true,
    frametitleaboveskip=\dimexpr-\ht\strutbox\relax,}
\begin{mdframed}[]\relax%
}{\end{mdframed}}


\begin{document}
    \section{Cats}
        Warm kitty, sweet kitty, little ball of fur. Warm kitty, sweet kitty, purr, purr, purr.

    \begin{definition}[Kitten.]
        A kitten is a baby cat.
    \end{definition}

    \begin{theorem}[Kittens are warm.]
        All kittens are warm.
    \end{theorem}
\end{document}

它产生以下输出:

在此处输入图片描述

我想定义一些其他的像这样的盒子,例如公理:

\newcounter{axiom}
\newenvironment{axiom}[1][]{%
\stepcounter{axiom}%
\ifstrempty{#1}%
{\mdfsetup{%
        frametitle={%
            \tikz[baseline=(current bounding box.east),outer sep=0pt]
            \node[anchor=east,rectangle,fill=white]
            {\strut Axiom~\theaxiom;}}
}%
{\mdfsetup{%
        frametitle={%
            \tikz[baseline=(current bounding box.east),outer sep=0pt]
            \node[anchor=east,rectangle,fill=white]
            {\strut Axiom~\theaxiom:~#1};}}%
}%
\mdfsetup{innertopmargin=1pt,linecolor=blue!60,%
    linewidth=2pt,topline=true,
    frametitleaboveskip=\dimexpr-\ht\strutbox\relax,}
\begin{mdframed}[]\relax%
}{\end{mdframed}}

请注意,这是除颜色之外的其他框定义的完全副本,以及框“类型”(例如公理、定义或定理)。

因此,我认为我不应该多次复制并粘贴此样式来创建新框,而应该以某种方式将定义放入宏中。因此,我决定将定义填充到宏中,\newcommand如下所示:

\newcommand{\defcustombox}[2]{%
\newenvironment{\expandafter\Makelowercase\expandafter{#1}}[1][]{%
\stepcounter{\expandafter\Makelowercase\expandafter{#1}}%
\ifstrempty{\#1}%
{\mdfsetup{%
        frametitle={%
            \tikz[baseline=(current bounding box.east),outer sep=0pt]
            \node[anchor=east,rectangle,fill=white]
            {\strut #1~\the<thing>};}}
}%
{\mdfsetup{%
        frametitle={%
            \tikz[baseline=(current bounding box.east),outer sep=0pt]
            \node[anchor=east,rectangle,fill=white]
            {\strut #1~\the<thing>:~##1};}}%
}%
\mdfsetup{innertopmargin=1pt,linecolor=#2!60,%
    linewidth=2pt,topline=true,
    frametitleaboveskip=\dimexpr-\ht\strutbox\relax,}
\begin{mdframed}[]\relax%
}{\end{mdframed}}
}

\defcustombox{Axiom}{blue} %example of expected usage

对于这次尝试,这些是我所知道的问题(如果你尝试的话,它不会编译):

  • 宏的“内容”必须逐字输出(请注意,我没有转义宏主体中的任何特殊字符);我确实尝试手动转义所有内容,但这很容易出错,而且似乎不是“正确的方法”
  • 嵌套参数必须加以区分!(我认为解决这个问题的方法是引用##1正在创建的宏的第一个参数时放在框中?我用它来区分内部命令的参数)
  • \the<thing>必须根据宏的第一个参数想出一种优雅的扩展方法\defcustombox——它看起来像什么\\the\expandafter\MakeLowercase\expandafter{#1}

为了实现这个目标我们应该怎么做呢?

答案1

像这样:

\documentclass{article}

\usepackage[framemethod=TikZ]{mdframed} % noteboxes, boxes, etc.

\newcommand{\definebox}[2]{%
  \newcounter{#1}
  \newenvironment{#1}[1][]{%
    \stepcounter{#1}%
    \mdfsetup{%
        frametitle={%
            \tikz[baseline=(current bounding box.east),outer sep=0pt]
            \node[anchor=east,rectangle,fill=white]
            {\strut \MakeUppercase#1~\csname the#1\endcsname\ifstrempty{##1}{}{:~##1}};}}%
    \mdfsetup{innertopmargin=1pt,linecolor=#2,%
        linewidth=2pt,topline=true,
        frametitleaboveskip=\dimexpr-\ht\strutbox\relax,}%
    \begin{mdframed}[]\relax%
    }{\end{mdframed}}%
}

\definebox{definition}{red!60}
\definebox{theorem}{black}

\begin{document}
    \section{Cats}
        Warm kitty, sweet kitty, little ball of fur. Warm kitty, sweet kitty, purr, purr, purr.

    \begin{definition}[Kitten.]
        A kitten is a baby cat.
    \end{definition}

    \begin{theorem}[Kittens are warm.]
        All kittens are warm.
    \end{theorem}
\end{document}

相关内容