[Tex/LaTex] Unbalanced braces with newenvironment / NewEnviron + Command

bracesenvironmentsmacros

This is a follow-up question of my Unbalanced braces with newenvironment / NewEnviron post. The gist is that by using

\NewEnviron{myEnv}{%
  \expandafter\gdef\expandafter\myCommand\expandafter{\BODY}%
  \aftergroup\bgroup}

I can expand

\begin{myEnv}
0.3
\end{myEnv} text2}

to

\gdef\myCommand
text1
{ text2}

This is working perfectly, thanks again egreg. Note that the braces were really unbalaced before expansion. Now I have come to a similar, yet slightly different situation. I want to expand

\begin{myEnv}
0.3
\end{myEnv} text2}

to

\gdef\myCommand
text1
\eatWhitespace{ text2}

with the 1-parametric command eatWhitespace.

With which definition of myEnv can I achieve that?

Background info:

Why would anyone ever do this? Well, I am using LyX, but I want to use the caption/subcaption package instead of the subfig package (see also subcaption vs. subfig: Best package for referencing a subfigure). I almost succeeded – the only problem is that the figure environment reacts very sensitive to all linebreaks, and LyX inserts plenty of them. This behavior of LyX is hardcoded, and I do not want to recompile it from scratch. So I worked around that problem entirely witout ERT … and by using dummy commands, which eat the whitespaces. This is an example of the generated LyX output (yes, it's ugly):

\newcommand{\dummy}{}
\newcommand{\eatWhitespace}[1]{}
\newcommand{\subfigureWidth}{}
\newcommand{\subfigureImage}{}
\newcommand{\subfigureBlock}[3]{%
    \begin{subfigure}[c]{#1\textwidth}\centering#2\caption{#3}\end{subfigure}}

and

\begin{figure}
\begin{centering}
\begin{myEnv}
0.3
\end{myEnv}

\dummy}\renewcommand{\subfigureImage}{\mbox{\!\!\!\!{\input{../test/images/im-14.tikz}}


\dummy}}\subfigureBlock{\subfigureWidth}{\subfigureImage}{1st image}\begin{myEnv}
0.3
\end{myEnv}

\dummy}\renewcommand{\subfigureImage}{\mbox{\!\!\!\!{\input{../test/images/im-15.tikz}}


\dummy}}\subfigureBlock{\subfigureWidth}{\subfigureImage}{2nd image}\begin{myEnv}
0.3
\end{myEnv}

\dummy}\renewcommand{\subfigureImage}{\mbox{\!\!\!\!{\input{../test/images/im-16.tikz}}


\dummy}}\subfigureBlock{\subfigureWidth}{\subfigureImage}{3rd image}
\par\end{centering}
\end{figure}

As you can see, when you insert after each \end{myEnv} an \eatWhitespace{ it makes sense (and is still ugly). The other whitespaces are taken care of by using mbox, which works. However, this is not possible for the length of the subfigure. Thus this crazy construction with myEnv and unbalanced braces is used.

Best Answer

[None of the code below is tested. Most of the examples should work, though, up to unbalanced braces or missing \makeatletter.]

Your struggle to work around (unreasonable) limitations of LyX (adding random blank lines) by working around (very reasonable) limitations of TeX (it almost exclusively manipulates balanced token lists) is certainly heroic. However, there are simpler ways to ignore blank lines.

  1. Delimited arguments instead of unbalanced braces.

    \long\def\gobbleuntildummy#1\dummy{}
    \newenvironment{myenv}{}{\aftergroup\gobbleuntildummy}
    \begin{myenv}
    \end{myenv}
    
    \dummy
    
  2. Changing category codes or the end-line character: this won't work within the argument of another macro.

    \newenvironment{ignoreallnewlines}
      {% Uncomment one line.
       % \endlinechar=-1\relax        % or 32 to get spaces
       % \catcode\endlinechar=9\relax % or 10 to get spaces 
      }{}
    \begin{ignoreallnewlines}
      He
      llo, wo
    
      rld!
    
    \end{ignoreallnewlines}
    
  3. Ignoring spaces and paragraph breaks after the end of an environment by recursively looking for them:

    \newenvironment{ignoreparsafter}{}{\aftergroup\@ignore@pars\par}
    \newcommand{\@ignore@pars}[1]{\@ifnextchar#1{\@ignore@pars}{}}
    \begin{ignoreparsafter}
      Hel%
    \end{ignoreparsafter}
    
    \par
    
    lo!
    
  4. [Don't do this.] Keeping your bizarre construction with unbalanced braces can be done in two ways: either with a box:

    \newenvironment{ignoreparsafter}{}{\aftergroup\@ignoreuntilbrace}
    \newcommand{\@ignoreuntilbrace}
      {\begingroup\setbox0\hbox\bgroup\aftergroup\endgroup}
    

    or with a brace trick (see the question on brace tricks):

    \newcommand{\@ignoreuntilbrace}
      {\expandafter\@gobble\expandafter{\iffalse}\fi}
    

I cannot help but notice that you are using the \centering command as an environment. Use either \begin{center}...\end{center}, or simply \centering in the scope of the environment whose text you wish to center.

Also... when LyX fails you, just use a text editor.

Related Question