# Custom align environment which auto breaks line before = and aligns at =

\documentclass{article}
\usepackage{mathtools}
\DeclareMathOperator{\lcm}{lcm}

\begin{document}
\begin{align*}
\lcm(13, 7) &= (13 \cdot 7):\gcd(13, 7) \\
&= (13 \cdot 7):1 \\
&= \overset{10+3}{13} \cdot 7 \\
&= 10 \cdot 7+3 \cdot 7 \\
&= 70+21 \\
&= \boxed{91}
\end{align*}
\end{document}


Is it possibile to define a custom environment, say customalign, which let obtain the same output by writing the equation on a single line like this?

\begin{customalign}
\lcm(13, 7) = (13 \cdot 7):\gcd(13, 7) = (13 \cdot 7):1 = \overset{10+3}{13} \cdot 7 = 10 \cdot 7+3 \cdot 7 = 70+21 = \boxed{91}
\end{customalign}


The customalign environment should automatically:

• breaks line before every = sign starting from the second one, ie it should auto adds \\ before every = sign starting from the second one;
• aligns at every = sign, ie it should auto adds & before every = sign but after the \\.

The customalign is defined using newenviron in order to tap into the \BODY of the environment. Every = is replaced by \\ &= via \xpatchcmd*. A second \xpatchcmd then restores the first global replacement back to only &=:

\documentclass{article}

\usepackage{mathtools,regexpatch,environ}
\DeclareMathOperator{\lcm}{lcm}

\NewEnviron{customalign}{%
\xpatchcmd*{\BODY}{=}{\\ &=}{}{}% Global replacement "=" > "\\ &="
\xpatchcmd{\BODY}{\\ &=}{&=}{}{}% First replacement "\\ &=" > "&="
\begin{align*}
\BODY% Set align with replacement
\end{align*}
}

\begin{document}

\begin{align*}
\lcm(13, 7) &= (13 \cdot 7) : \gcd(13, 7) \\
&= (13 \cdot 7) : 1 \\
&= \overset{10 + 3}{13} \cdot 7 \\
&= 10 \cdot 7 + 3 \cdot 7 \\
&= 70 + 21 \\
&= \boxed{91}
\end{align*}

\begin{customalign}
\lcm(13, 7) = (13 \cdot 7) : \gcd(13, 7)
= (13 \cdot 7) : 1
= \overset{10 + 3}{13} \cdot 7
= 10 \cdot 7 + 3 \cdot 7
= 70 + 21
= \boxed{91}
\end{customalign}

\end{document}

• Thank you very much, I get this warning though Package l3regex Warning: This package is obsolete --- use 'expl3', is something to be worried of? – sound wave Oct 19 at 5:12
• @soundwave: I have an up-to-date version of TeX Live (here is my file list; obtained by adding \listfiles to your preamble and examining the .log). Update all your packages and try again, maybe? – Werner Oct 19 at 5:40
• I think it is a problem with overleaf, not a big deal I guess, thanks! – sound wave Oct 19 at 6:03
• I appreciate both answers, but accepted this since it's the only one working in quicklatex. – sound wave Oct 19 at 9:30
• @Werner you and egreg introduced auto breaking to the the next generation level...Thank you both... – MadyYuvi Oct 21 at 11:43

This implementation avoids cumbersome replacements:

1. the body of the environment is split at =;
2. the first item is set apart and passed to split followed by &=;
3. the remaining item are delivered, separated by \\ &=.
\documentclass{article}
\usepackage{mathtools}
\usepackage{xparse}

\DeclareMathOperator{\lcm}{lcm}

\ExplSyntaxOn

\NewDocumentEnvironment{breakalign}{b}
{
\soundwave_breakalign:nnn { #1 } { split } { }
}
{}
\NewDocumentEnvironment{breakalign*}{b}
{
\begin{equation*}\soundwave_breakalign:nnn { #1 } { split } { }\end{equation*}
}
{}
\NewDocumentEnvironment{breakaligned}{O{c} b}
{
\soundwave_breakalign:nnn { #2 } { aligned } { #1 }
}
{}

\tl_new:N \l__soundwave_breakalign_left_tl
\seq_new:N \l__soundwave_breakalign_body_seq

\cs_new_protected:Nn \soundwave_breakalign:nnn
{
\seq_set_split:Nnn \l__soundwave_breakalign_body_seq { = } { #1 }
\seq_pop_left:NN \l__soundwave_breakalign_body_seq \l__soundwave_breakalign_left_tl
\tl_if_empty:nTF { #3 } { \begin{#2} } { \begin{#2}[#3] }
\l__soundwave_breakalign_left_tl &=
\seq_use:Nn \l__soundwave_breakalign_body_seq { \\ &= }
\end{#2}
}

\ExplSyntaxOff

\begin{document}

\begin{breakalign*}
\lcm(13, 7) = (13 \cdot 7):\gcd(13, 7)
= (13 \cdot 7):1
= \overset{10+3}{13} \cdot 7
= 10 \cdot 7+3 \cdot 7
= 70+21
= \boxed{91}
\end{breakalign*}

\begin{breakalign}
\lcm(13, 7) = (13 \cdot 7):\gcd(13, 7)
= (13 \cdot 7):1
= \overset{10+3}{13} \cdot 7
= 10 \cdot 7+3 \cdot 7
= 70+21
= \boxed{91}
\end{breakalign}

\begin{align*}
&\begin{breakaligned}
\lcm(13, 7) = (13 \cdot 7):\gcd(13, 7)
= (13 \cdot 7):1
= \overset{10+3}{13} \cdot 7
= 10 \cdot 7+3 \cdot 7
= 70+21
= \boxed{91}
\end{breakaligned}
&&
\begin{breakaligned}
\lcm(13, 7) = (13 \cdot 7):\gcd(13, 7)
= (13 \cdot 7):1
= \overset{10+3}{13} \cdot 7
= 10 \cdot 7+3 \cdot 7
= 70+21
= \boxed{91}
\end{breakaligned}
\end{align*}

\end{document}


There are three environments:

1. breakalign will get a number;
2. breakalign* will be unnumbered;
3. breakaligned can be used as a subsidiary environment and accepts the usual [t] or [b] options like aligned for vertical alignment.

A version compatible with older (but not too old) versions of TeX Live.

\documentclass{article}
\usepackage{mathtools}
\usepackage{xparse}
\usepackage{environ}

\DeclareMathOperator{\lcm}{lcm}

\ExplSyntaxOn

\NewEnviron{breakalign}
{
\soundwave_breakalign:Vnn \BODY { split } { }
}

\NewEnviron{breakalign*}
{
\begin{equation*}\soundwave_breakalign:Vnn \BODY { split } { }\end{equation*}
}

\NewEnviron{breakaligned}[1][c]
{
\soundwave_breakalign:Vnn \BODY { aligned } { #1 }
}

\tl_new:N \l__soundwave_breakalign_left_tl
\seq_new:N \l__soundwave_breakalign_body_seq

\cs_new_protected:Nn \soundwave_breakalign:nnn
{
\seq_set_split:Nnn \l__soundwave_breakalign_body_seq { = } { #1 }
\seq_pop_left:NN \l__soundwave_breakalign_body_seq \l__soundwave_breakalign_left_tl
\tl_if_empty:nTF { #3 } { \begin{#2} } { \begin{#2}[#3] }
\l__soundwave_breakalign_left_tl &=
\seq_use:Nn \l__soundwave_breakalign_body_seq { \\ &= }
\end{#2}
}
\cs_generate_variant:Nn \soundwave_breakalign:nnn { V }

\ExplSyntaxOff

\begin{document}

\begin{breakalign*}
\lcm(13, 7) = (13 \cdot 7):\gcd(13, 7)
= (13 \cdot 7):1
= \overset{10+3}{13} \cdot 7
= 10 \cdot 7+3 \cdot 7
= 70+21
= \boxed{91}
\end{breakalign*}

\begin{breakalign}
\lcm(13, 7) = (13 \cdot 7):\gcd(13, 7)
= (13 \cdot 7):1
= \overset{10+3}{13} \cdot 7
= 10 \cdot 7+3 \cdot 7
= 70+21
= \boxed{91}
\end{breakalign}

\begin{align*}
&\begin{breakaligned}
\lcm(13, 7) = (13 \cdot 7):\gcd(13, 7)
= (13 \cdot 7):1
= \overset{10+3}{13} \cdot 7
= 10 \cdot 7+3 \cdot 7
= 70+21
= \boxed{91}
\end{breakaligned}
&&
\begin{breakaligned}
\lcm(13, 7) = (13 \cdot 7):\gcd(13, 7)
= (13 \cdot 7):1
= \overset{10+3}{13} \cdot 7
= 10 \cdot 7+3 \cdot 7
= 70+21
= \boxed{91}
\end{breakaligned}
\end{align*}

\end{document}

• Thank you very much, I get this error though LaTeX error: "xparse/unknown-argument-type" Unknown argument type 'b' for the command '\environment breakalign'. for each environment (I'm using overleaf). – sound wave Oct 19 at 5:10
• @soundwave Set up Overleaf to use TeX Live 2018 – egreg Oct 19 at 8:07
• This compiles fine on TL2019, but still errors on TL2018. – LianTze Lim Oct 21 at 9:47
• @LianTzeLim OK, I added a version for Overleaf. – egreg Oct 21 at 9:56
• @egreg One of a great suggestion...Thanks a lot...It helps me too... – MadyYuvi Oct 21 at 11:44

Another (slightly fragile) option is the use breqn, which is the experimental package for automatic line-breaking.

By default, breqn will also include linebreaks as :, so we need to hide them using \hiderel{:}. Here is the complete code:

\documentclass{article}
\usepackage{amsmath,breqn}
\DeclareMathOperator{\lcm}{lcm}

\begin{document}
\begin{dmath*}
\lcm(13, 7) = (13 \cdot 7) \hiderel{:}\gcd(13, 7)
= (13 \cdot 7)\hiderel{:}1
= \overset{10+3}{13} \cdot 7
= 10 \cdot 7+3 \cdot 7
= 70+21
= \boxed{91}
\end{dmath*}
\end{document}