Is there a way to make sure that a macro can only be used inside a specific environment, say description
?
I am looking for something like the \ensuremath
macro.
You can modify the definition of the environment in order to set the command to either work or not. For the description
environment, you could use the following code for example:
\documentclass{article}
\let\olddesc\description
\def\myrealcmd#1{\textbf{#1}}
\def\myfakecmd#1{#1}
\let\mycmd\myfakecmd
\def\description{\let\mycmd\myrealcmd\olddesc}
\begin{document}
\noindent This is a \mycmd{test} outside of description.
\begin{description}
\item This is a \mycmd{test} inside of one description.
\begin{description}
\item This is a \mycmd{test} inside of two descriptions.
\end{description}
\item This is a \mycmd{test} after a nested description.
\end{description}
And a \mycmd{test} outside again.
\end{document}
With the following result:
description
, the end code will be run…
\mycmd
to \fakecmd
.
Feb 1, 2012 at 0:50
The etoolbox
package provides hooks for the environments; so you can define a "hidden" macro and then activate it only in selected environments
\usepackage{etoolbox}
\makeatletter % protect the definition of \mymacro
\newcommand{\@mymacro}{whatever}
\AtBeginEnvironment{description}{\let\mymacro\@mymacro}
\makeatother
% now we help users
\newcommand{\mymacro}{%
\PackageError{mypackage}
{\protect\mymacro\space outside `description'}
{You can use \protect\mymacro\space only inside `description'}%
}
You can add other environments and also provide a different meaning in different environments:
\usepackage{etoolbox}
\makeatletter % protect the definition of \mymacro
\newcommand{\description@mymacro}{whatever}
\AtBeginEnvironment{description}{\let\mymacro\description@mymacro}
\newcommand{\itemize@mymacro}{whatever}
\AtBeginEnvironment{itemize}{\let\mymacro\itemize@mymacro}
\makeatother
\PackageError
needs a space following \protect\mymacro
. I tried the usual \
and ~
but I guess that is not the correct way to insert space there.
Jan 31, 2012 at 16:50
\space
(I always forget). One can use \noexpand
instead of \protect
, but the latter is good practice.
The current environment name is stored in \@currenvir
so you could test that that was description
or whatever, but nested environments would mask that. If you need your macro to be allowed anywhere in description, even in a nested tabular or itemize, say, then you would need to save \@currenvir
into another macro at the start of description (either explicitly or by patching the definition of \description
then you can test this local macro without it being over-written by nested environments.
\ensuremath
macro switches to math mode to typeset its argument if necessary. If your macro is called outside adescription
, do you want it to flag an error, or start adescription
?