5

I'm trying to Add a marginal note when a page break occurs in the middle of a multi-line equation, using the nice method provided by egreg in its answer to my question: Disable fleqn option for multline environments?

Since page breaks may occur in the middle of both align and flalign environments, I'm trying to patch both of them in the spirit of the minimized example below (which has the nice feature to add "foo" and "bar" respectively before and after each \\ encountered in these environments).

The problem is, this patch works nicely for align but fails for flalign: as soon as the latter is uncommented in the document body, the compilation fails with the error:

! Missing } inserted.
<inserted text> 
                }
l.78 \end{flalign}

and this happens even if flalign isn't patched, i.e. if :

\clist_set:Nn \l_tmpa_clist {align,flalign}

is replaced by :

\clist_set:Nn \l_tmpa_clist {align}

Do you see what's going on and how to make this patch working for flalign as well? (The same question could be asked for alignat.)

\documentclass[fleqn]{report}
\usepackage{amsmath}
\usepackage{xparse,environ}

\ExplSyntaxOn
\makeatletter

\clist_set:Nn \l_tmpa_clist {align,flalign}
\clist_map_inline:Nn \l_tmpa_clist {
  % save the original environments
  \cs_set_eq:cc {db_#1_start:} {#1}
  \cs_set_eq:cc {db_#1_end:} {end#1}
  \cs_set_eq:cc {db_#1_star_start:} {#1*}
  \NewDocumentEnvironment{amsmath#1}{}
  {\cs:w db_#1_start:\cs_end:}
  {\cs:w db_#1_end:\cs_end:}
  \NewDocumentEnvironment{amsmath#1*}{}
  {\cs:w db_#1_star_start:\cs_end:}
  {\cs:w db_#1_end:\cs_end:}
  \RenewEnviron{#1}
  {
    \cs:w db_patch:nV\cs_end: {#1} \BODY
  }
  \RenewEnviron{#1*}
  {
    \cs:w db_patch:nV\cs_end: {#1*} \BODY
  }
}
% redefine them
\seq_new:N \l_db_patch_seq
\cs_new_protected:Nn \db_patch:nn
 {
  \seq_set_split:Nnn \l_db_patch_seq { \\ } { #2 }
  \begin{amsmath#1}
    \seq_use:Nn \l_db_patch_seq { \db@patch } \hfill
  \end{amsmath#1}
 }
\cs_generate_variant:Nn \db_patch:nn { nV }

\NewDocumentCommand{\db@patch}{so}{%
  \quad\text{foo}
  \IfValueTF{#2}{%
    \IfBooleanTF{#1}{\\*[#2]}{\\[#2]}%
  }{%
    \IfBooleanTF{#1}{\\*}{\\}
  }%
  \text{bar}\quad
}

\makeatother
\ExplSyntaxOff

\begin{document}
\begin{align}
  1 + 1 & = 2 \\
  2 + 1 & = 3 \\
  3 + 1 & = 4 \\
  4 + 1 & = 5 \\
  5 + 1 & = 6 \\
  6 + 1 & = 7 \\
  7 + 1 & = 8 \\
  8 + 1 & = 9 \\
  9 + 1 & = 10
\end{align}

% \begin{flalign}
%   1 + 1 & = 2 \\
%   2 + 1 & = 3 \\
%   3 + 1 & = 4 \\
%   4 + 1 & = 5 \\
%   5 + 1 & = 6 \\
%   6 + 1 & = 7 \\
%   7 + 1 & = 8 \\
%   8 + 1 & = 9 \\
%   9 + 1 & = 10
% \end{flalign}
\end{document}
  • Don't use flalign, it's easier. – egreg Nov 6 '17 at 17:24
  • @egreg This patch is supposed to be part of a class, the users of which a priori allowed to use flalign. Admittedly, I could refrain them to use it by redefining it to \relax with an error message advising to just use align instead; but, even this, I can't do it AFAICS. – Denis Bitouzé Nov 6 '17 at 17:38
  • I managed to redefine flalign to \relax (with an error message advising to just use align instead) but I would prefer to patch it just like I could patch align. – Denis Bitouzé Nov 9 '17 at 6:40
  • You could just set flalign equal to align and issue a warning message. If this is a house style, imposing that style is what the class is meant to do. – cfr Nov 12 '17 at 4:48
  • @cfr That's what's I did as a workaround and, indeed, that's what I'd like for the house style. For alignat, though, it could be reasonable to let the users still use its features. – Denis Bitouzé Nov 12 '17 at 11:22
3
+200

The issue is that when you redefine align, that redefines the command \endalign, which (if you check out the source for amsmath) is used as the end of all the alignment environments.

A solution would be to patch it in a different manner, as follows:

\usepackage{xparse,etoolbox}

%Beggining Same as in the question
\ExplSyntaxOn
\makeatletter
\clist_set:Nn \l_tmpa_clist {flalign,align}
\clist_map_inline:Nn \l_tmpa_clist {
%We use collect@body, which is what's used internally by NewEnviron
%It takes in the environment body, and then calls the next cs
  \AtBeginEnvironment{#1}{\collect@body\db_patch:n}
}
% redefine them
\seq_new:N
\l_db_patch_seq
\cs_new_protected:Nn
\db_patch:n
{
  \seq_set_split:Nnn
  \l_db_patch_seq {
  \\ } { #1 }
    \seq_use:Nn
    \l_db_patch_seq
    { \db@patch
    } 
}
%The remainder as in the question

Here, we only patch the beggining of the environments, using old fashioned tools from etoolbox, avoiding redefining the \endalign.

It's also worth noting that you don't need the environ package, because amsmath also defines the \collect@body command which we use to read in the environment.

  • Sigh... shame on me! Is it possible to re-offer a bounty? – Denis Bitouzé Nov 20 '17 at 6:39
  • 1
    Think so. Might cost you double, though. – A Gold Man Nov 20 '17 at 6:40
  • Bounty re-offered! :) – Denis Bitouzé Nov 20 '17 at 6:45

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.