3

I want to define a new command that is similar to \addstackgap from stackengine package except that it has an optional argument. The command modifies the small stack gap so that the preferred amount of padding is adding above and under the argument. However, after the command ends, the amount allocated to small stack gap must go back to its normal value, which is done by using \stackgapSdefault command defined here. Here is an example:

\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}

The gap in \stackanchor{Top}{Bottom} must be 10mm as specified in the default settings. If we put \stackgapSdefault after the equation environment, the gap resets to its default value, but it should have automatically reset because \stackgapSdefault is already included in \stackgapadd. How can I force stackgapSdefault it to take effect even when it is inside math mode?

2 Answers2

3

The problem here is that \setstackgap internally calls \@namedef which in turn defines a new macro name using the TeX primitive \def. Such (re)definitions are only available in local groups (more about grouping here), like the one implicitly introduced by \begin/\end. That means when the \end is executed, the old definition made to the stack gaps are restored.

As a simple solution, we can redefine \setstackgap such that all definitions are made in global scope. Put the following code right after \usepackage{stackengine}:

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

(In case you absolutely need local and global definitions, you'd leave the \setstackgap command as it is and define a new command like the one above for global definitons.)

siracusa
  • 13,411
2

Since the only two valid options for argument #1 of \setstackgap are S and L (for "short" and "long" stacks), you can manually \gdef the desired global setting with

\gdef\Sstackgap{<gap>}

in lieu of the local \setstackgap{S}{<gap>} or

\gdef\Lstackgap{<baseline skip>}

in lieu of the local \setstackgap{L}{<baseline skip>}.

In terms of the OP's code, however, you need an \xdef, because you want the default argument to \stackgapadd to be the current value of \Sstackgap and a \def or \gdef argument cannot contain itself:

\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}

enter image description here

Now, I don't recommend the following, but it seems you really want these stack gaps to be immutable things, not subject to the vagaries of scope and group. In the original incarnation of the stackengine package, \Sstackgap and \Lstackgap were defined as lengths, rather than \defs. In LaTeX, lengths are a global setting. And so another option is to invoke the [oldsyntax] option of the package, and use those settings as lengths, not defs.

\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}