1

I need to place a user defined environment within another environment, either alone or after some text, and I want that a vertical space is automatically insterted only in the latter case. In other words, I want to define environment2 so that there's some vertical space before it in this case

\begin{environment}
Text
      <--- space here
\begin{environment2}
Text
\end{environment2}
\end{environment}

but not in this case:

\begin{environment}
\begin{environment2}
Text
\end{environment2}
\end{environment}
  • Of course, you are using the environment environment only between paragraphs. aren’t you? – GuM Nov 21 '17 at 13:09
  • Yes, of course. In fact, my environment defines a marginal note through wrapfigure – Massimo Nov 21 '17 at 13:48
1

The typical technique for addressing this kind of problem is to use the \everypar hook, which gets executed every time TeX begins a new paragraph. So you can have a switch, say \if@EnvOneHasText@, which you set to false when you begin the outer environment, while adding to the \everypar hook an instruction that sets the same switch to true. Then you test this switch at the beginning of the inner environment:

  • if you find that it is still false, then you know that TeX didn’t begin any paragraph since the outermost environment has begun, so you do not add the vertical space;

  • if, on the other hand, you find that it has become true, you know that TeX found some text between the beginning of the outer environment and the beginning of the inner one, that forced it to start a new paragrph, so you do add the vertical space.

Here’s a MWE that illustrates this technique:

% My standard header for TeX.SX answers:
\documentclass[a4paper]{article} % To avoid confusion, let us explicitly 
                                 % declare the paper format.

\usepackage[T1]{fontenc}         % Not always necessary, but recommended.
% End of standard header.  What follows pertains to the problem at hand.

\makeatletter

\@ifdefinable\if@EnvOneHasText@{\newif\if@EnvOneHasText@}

\newenvironment*{environment1}{%
    \par % make sure we terminate any preceding paragraph
    % The following is just to mark where the environment begins;
    % you should substitute your real code here:
    \addvspace{\bigskipamount}%
    \noindent Begin of \texttt{environment1}.\par
    % The following two lines do the trick:
    \@EnvOneHasText@false
    \everypar \expandafter{\the\everypar \@EnvOneHasText@true}%
}{%
    \par
    % Add whatever you need here.
    \noindent End of \texttt{environment1}.\par
    \addvspace{\bigskipamount}% for example
}

\newenvironment*{environment2}{%
    \par
    \if@EnvOneHasText@
        \addvspace{\bigskipamount}% say
    \fi
    % The following is just to mark where the environment begins;
    % you should substitute your real code here:
    \noindent
    Begin of \texttt{environment2}.\par
}{
    \par
    % Add whatever you need here.
    \noindent End of \texttt{environment2}.\par
}

\makeatother



\begin{document}

Some text to begin with.

\begin{environment1}
    \begin{environment2}
        Some text inside the innermost environment.
    \end{environment2}
\end{environment1}

Words words words words\ldots

\begin{environment1}
    Some text in between.
    \begin{environment2}
        Some text inside the innermost environment.
    \end{environment2}
\end{environment1}

Words words words words\ldots

\begin{environment1}
    Does it nest correctly?
    \begin{environment2}
        Some text inside the outer \texttt{environment2} environment.
        \begin{environment1}
            \begin{environment2}
                Some text inside the inner \texttt{environment2} environment.
                There should be no space above this text.
            \end{environment2}
            We are now inside the inner \texttt{environment1} environment.
        \end{environment1}
    \end{environment2}
\end{environment1}

\end{document}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.