27

I would like to define a command which checks if it is executed inside a certain environment. Like this:

\documentclass{article}

\newenvironment{myenv}[0]{at start}{ at end}

\newcommand{\inner}[0]{%
  % if iside a myenv
  (inner)
  % else
  \begin{myenv}
  (inner)%
  \end{myenv}
  % end
}

\begin{document}

\begin{myenv}
  \inner
\end{myenv}

\inner

\end{document}

See the definition of \inner. Is an if-condition of this form possible?

lockstep
  • 250,273

2 Answers2

25

LaTeX keeps the current environment in the macro \@currenvir

\makeatletter
\newcommand{\inner}{%
  \ifx\@currenvir\@myenvname
    (inner)
  \else
    \begin{myenv}(inner)\end{myenv}
  \fi}
\newcommand*\@myenvname{myenv}
\makeatother

Another approach would be to define a global conditional that's set to true by myenv start code and to false by myenv end code. It depends mostly on what you are expecting from the myenv environment: can it appear nested inside itself?

egreg
  • 1,121,712
  • 3
    @Nickoley: Note that this doesn't work any longer when \inner is used inside another environment inside the myenv environment, e.g. \begin{myenv}\begin{center}\inner\end{center}\end{myenv}. Then@currenvirwill becenterwhen\inner` is expanded. – Martin Scharrer May 20 '11 at 10:28
  • This does not seem to work on my end. It produces the "else" output both inside and outside a myenv environment. However, both \@currenvir and \@myenvname display the correct (and the same) output when placed inside the environment. – Danny Mar 25 '19 at 21:33
  • 2
    @DannyHansen Right: in some update during the last eight years, the LaTeX kernel changed \@currenvir to not be \long as it used to be. Fixed by adding a *. – egreg Mar 25 '19 at 21:41
5

If you use pdftex, etex or xetex (I mean engine), you can define a fully expandable test:

\makeatletter \def\IfEnvir #1%
% implicit #2 "what if true"
% implicit #3 "what if false"
{%
  \ifnum \strcmp{\@currenvir}{#1}=0
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}

\makeatother

Such a conditional is defined in the gmutils package: \@ifenvir, but there it's \protected for some reason.

Martin Scharrer
  • 262,582
Natror
  • 71
  • If you prefer the \if… … \else … \fi form, just replace \expandafter@first/secondoftwo with your stuff, but i'd suggest the arguments-form because it's robust to unbalanced \if's. – Natror May 20 '11 at 09:06
  • Please indent your code with four spaces (or use the '101010' button to do this) so that it is properly highlighted. Please don't use HTML for code formatting. Thanks. – Martin Scharrer May 20 '11 at 09:39
  • the command is \strcmp in XeTeX and \pdfstrcmp in pdfTeX. One can load pdftexcmds and use \pdf@strcmp in all engines (including LuaTeX). – egreg May 20 '11 at 10:04