即使在数学环境中调用,如何强制自定义命令生效?

即使在数学环境中调用,如何强制自定义命令生效?

我想定义一个新命令,它类似于\addstackgapfromstackengine包,只是它有一个可选参数。该命令修改小堆栈间隙,以便首选的填充量添加到参数的上方和下方。但是,在命令结束后,分配给小堆栈间隙的量必须恢复到其正常值,这是通过使用\stackgapSdefault此处定义的命令来完成的。以下是一个例子:

\documentclass{IEEEtran}

\usepackage{array}
\usepackage{amsmath,amsfonts}

\usepackage{stackengine}
    \newlength{\stackgapSdefaultl}
    \setlength{\stackgapSdefaultl}{10mm}

    \newcommand{\stackgapLdefault}{
        \setstackgap{L}{\stackgapLdefaultl}
                                }

    \newcommand{\stackgapSdefault}{
        \setstackgap{S}{\stackgapSdefaultl}
                                }

    \newcommand{\stackgapadd}[2][\stackgapSdefaultl]{
        \renewcommand{\stacktype}{S} \setstackgap{S}{#1} \addstackgap{#2} \stackgapSdefault
                                                }   


\begin{document}


\begin{equation}
    \left[
        \stackgapadd{$e = m c^{2}$}
    \right]
\end{equation}


\stackanchor{Top}{Bottom}

\end{document}

中的间隙\stackanchor{Top}{Bottom}必须10mm与默认设置中指定的一样。如果我们\stackgapSdefault在方程环境后放置,间隙将重置为其默认值,但它应该会自动重置,因为\stackgapSdefault已经包含在中\stackgapaddstackgapSdefault即使处于数学模式中,我怎样才能强制它生效?

答案1

这里的问题是\setstackgap内部调用 ,\@namedef而后者又使用 TeX 原语 定义了一个新的宏名\def。此类(重新)定义仅在本地组中可用(有关分组的更多信息这里\begin),就像/隐式引入的一样\end。这意味着当\end执行时,对堆栈间隙的旧定义将被恢复。

作为一个简单的解决方案,我们可以重新定义\setstackgap,以便所有定义都在全局范围内进行。将以下代码放在后面\usepackage{stackengine}

\renewcommand{\setstackgap}[2]{%
    \expandafter\gdef\csname#1stackgap\endcsname{#2}%
}

(如果您确实需要本地和全局定义,您可以保留\setstackgap原样的命令并定义一个新命令,如上面的全局定义命令。)

答案2

#1由于参数的唯一两个有效选项\setstackgapSL(分别用于“短”堆栈和“长”堆栈),因此您可以使用以下方式手动\gdef设置所需的全局设置:

\gdef\Sstackgap{<gap>}

代替当地\setstackgap{S}{<gap>}

\gdef\Lstackgap{<baseline skip>}

代替当地的\setstackgap{L}{<baseline skip>}

但是,就OP的代码而言,您需要一个\xdef,因为您希望默认参数是\stackgapadd的当前值\Sstackgap,并且\def\gdef参数不能包含其自身:

\documentclass{IEEEtran}

\usepackage{array}
\usepackage{amsmath,amsfonts}

\usepackage{stackengine}
\setstackgap{L}{10mm}
\setstackgap{S}{10mm}

\newcommand{\stackgapadd}[2][\Sstackgap]{
  \renewcommand{\stacktype}{S}\xdef\Sstackgap{#1}\addstackgap{#2}}   

\begin{document}

\begin{equation}
    \left[
        \stackgapadd{$e = m c^{2}$}
    \right]
\end{equation}

\stackanchor{Top}{Bottom}

\end{document}

在此处输入图片描述

现在,我不推荐以下做法,但似乎您确实希望这些堆栈间隙是不可变的,不受范围和组变化的影响。在包的原始版本中stackengine\Sstackgap\Lstackgap被定义为长度,而不是\defs。在 LaTeX 中,长度是一个全局设置。因此,另一个选项是调用[oldsyntax]包的选项,并将这些设置用作长度,而不是 def。

\documentclass{IEEEtran}

\usepackage{array}
\usepackage{amsmath,amsfonts}

\usepackage[oldsyntax]{stackengine}
\setlength{\Lstackgap}{10mm}
\setlength{\Sstackgap}{10mm}

\newcommand{\stackgapadd}[2][\Sstackgap]{
  \renewcommand{\stacktype}{S}\setlength\Sstackgap{#1}\addstackgap{#2}}   

\begin{document}

\begin{equation}
    \left[
        \stackgapadd{$e = m c^{2}$}
    \right]
\end{equation}

\stackanchor{Top}{Bottom}

\end{document}

相关内容