1

I am trying to measure the natural width of an align* (with the fleqn documentclass option) and have been told in the comments at Determine natural width of align*: varwidth uses \linewidth even though display is correct that \intertext uses the entire \linewidth. So, solution sounds simple, redefine \intertext (and \shortintertext and measure them separately via \varwidth.

The problem is that it seems tricky to redfine those two macros as using a \let seems to be ingored. The MWE is intended to address the last two test cases by measuing the width of the \intertext and \shorintertext separately from the remainder of the align*.

enter image description here

References:

Code:

\documentclass[fleqn]{article}
\usepackage{etoolbox}
\usepackage{mathtools}
\usepackage{varwidth}

\usepackage{printlen}
\uselengthunit{mm}

\makeatletter
%% Fix for varwidth to work with fleqn option
%% https://tex.stackexchange.com/questions/394778/align-in-varwidth-seems-to-ignore-fleqn-option
\let\@vwid@eqmodetrue\@vwid@eqmodefalse

\newsavebox{\@IntertextSavebox}
\newlength{\@MaxIntertextWidth}
\newcommand{\MeasureIntertext}[1]{%
    \savebox{\@IntertextSavebox}{%
        \begin{varwidth}{\linewidth}
            #1%
        \end{varwidth}%
    }%
    %% Keep track of the maximum width of any \shorintertext and
    %% \intertext within this align* environment.
    \ifdim\wd\@IntertextSavebox>\@MaxIntertextWidth
        \setlength{\@MaxIntertextWidth}{\wd\@IntertextSavebox}%
    \fi
}%
\newsavebox{\@NonIntertextBox}
\newcommand{\GetNaturalVarwidth}[3]{%
    %% #1 = length to contain the width
    %% #2 = title for this test case
    %% #3 = text to measure
    \setlength{\@MaxIntertextWidth}{0pt}%
    \savebox{\@NonIntertextBox}{%
        \begin{varwidth}{\linewidth}
            %% ------------------------------------------------------ Problem Area
            %% This attempt to redefine these two seems to be ignored.
            \let\shortintertext\MeasureIntertext
            \let\intertext\MeasureIntertext
            %% ------------------------------------------------------ 
            #3%
        \end{varwidth}%
    }%
    %% ------------------------------------------
    %% For debugging purposes show the box.
    \medskip\par
    \noindent%
    {\bfseries#2}%
    \par\noindent
    \fboxsep=0pt
    \fbox{%
        \usebox{\@NonIntertextBox}%
    }%
    \ifdim\wd\@IntertextSavebox>\wd\@NonIntertextBox
        \setlength{#1}{\wd\@IntertextSavebox}%
    \else
        \setlength{#1}{\wd\@NonIntertextBox}%
    \fi
    {\par\tiny Natural Width is \printlength{#1}.}%
}%
\makeatother

\newlength{\NaturalWidth}
\begin{document}
\GetNaturalVarwidth{\NaturalWidth}{Small text}{Small text}% Works

%% These two don't work, but right now am just focusing on align*
%\GetNaturalVarwidth{\NaturalWidth}{Single Display Equation}{%
%\[
%    F = ma.
%\]
%}
%
%\GetNaturalVarwidth{\NaturalWidth}{Single display equation with text}{%
%Single display equation
%\[
%    F = ma.
%\]
%and some more text.%
%}

\GetNaturalVarwidth{\NaturalWidth}{Single align*}{%
\begin{align*}
    F &= ma.
\end{align*}%
}

\GetNaturalVarwidth{\NaturalWidth}{Align* with text}{%
Famous Equations:
\begin{align*}
    F &= ma. \\
    E &= mc^2,
\end{align*}%
or at least they should be famous.
}

\GetNaturalVarwidth{\NaturalWidth}{Align* with shortintertext}{%
\begin{align*}
    F &= ma. \\
    \shortintertext{and}
    E &= mc^2,
\end{align*}%
}
This one above should be 23.42914mm.

\GetNaturalVarwidth{\NaturalWidth}{Align* with intertext}{%
\begin{align*}
    F &= ma. \\
    \intertext{with some longer intertext}
    E &= mc^2,
\end{align*}%
}
This one above should be greater than 23.42914mm 
(which is width of just the nonintertext portion).

\end{document}

Listfiles

Am getting an error

Undefined control sequence.
\shortintertext ...th }\normalbaselines \if_dim:w

while running the provided answer so thought I should include the output of \listfiles:

 *File List*
 article.cls    2014/09/29 v1.4h Standard LaTeX document class
   fleqn.clo    2016/12/29 v1.2a Standard LaTeX option (flush left equations)
  size10.clo    2014/09/29 v1.4h Standard LaTeX file (size option)
etoolbox.sty    2018/02/11 v2.5e e-TeX tools for LaTeX (JAW)
mathtools.sty    2018/01/08 v1.21 mathematical typesetting tools
  keyval.sty    2014/10/28 v1.15 key=value parser (DPC)
    calc.sty    2014/10/28 v4.3 Infix arithmetic (KKT,FJ)
 mhsetup.sty    2017/03/31 v1.3 programming setup (MH)
 amsmath.sty    2017/09/02 v2.17a AMS math features
 amstext.sty    2000/06/29 v2.01 AMS text
  amsgen.sty    1999/11/30 v2.0 generic functions
  amsbsy.sty    1999/11/29 v1.2d Bold Symbols
  amsopn.sty    2016/03/08 v2.02 operator names
varwidth.sty    2009/03/30 ver 0.92;  Variable-width minipages
printlen.sty    2009/09/03 v1.1a print lengths with units
graphicx.sty    2017/06/01 v1.1a Enhanced LaTeX Graphics (DPC,SPQR)
graphics.sty    2017/06/25 v1.2c Standard LaTeX Graphics (DPC,SPQR)
    trig.sty    2016/01/03 v1.10 sin cos tan (DPC)
graphics.cfg    2016/06/04 v1.11 sample graphics configuration
  pdftex.def    2018/01/08 v1.0l Graphics/color driver for pdftex
supp-pdf.mkii
epstopdf-base.sty    2016/05/15 v2.6 Base part for package epstopdf
infwarerr.sty    2016/05/16 v1.4 Providing info/warning/error messages (HO)
  grfext.sty    2016/05/16 v1.2 Manage graphics extensions (HO)
kvdefinekeys.sty    2016/05/16 v1.4 Define keys (HO)
 ltxcmds.sty    2016/05/16 v1.23 LaTeX kernel commands for general use (HO)
kvoptions.sty    2016/05/16 v3.12 Key value format for package options (HO)
kvsetkeys.sty    2016/05/16 v1.17 Key value parser (HO)
etexcmds.sty    2016/05/16 v1.6 Avoid name clashes with e-TeX commands (HO)
ifluatex.sty    2016/05/16 v1.4 Provides the ifluatex switch (HO)
pdftexcmds.sty    2018/01/21 v0.26 Utility functions of pdfTeX for LuaTeX (HO)
   ifpdf.sty    2017/03/15 v3.2 Provides the ifpdf switch
epstopdf-sys.cfg    2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Live
 ***********
1

Package amsmath defines \intertext to cause an error message, if it is used outside of some environments, where it is supported. It uses \intertext@ to define \intertext in these environments. Therefore, \intertext@ needs to be redefined.

\shortintertext is provided by package mathtools and can be redefined directly.

The following code snippet replaces \vbox{...} by \begin{varwidth}{\linewidth}...\end{varwidth} in \intertext and \shortintertext:

\def\intertext@measuring{% see \intertext@ in amsmath
  \def\intertext##1{%
    \ifvmode\else\\\@empty\fi
    \noalign{%
      \penalty\postdisplaypenalty\vskip\belowdisplayskip
      %\vbox{
      \begin{varwidth}{\linewidth}%
        \normalbaselines
        \ifdim\linewidth=\columnwidth
        \else \parshape\@ne \@totalleftmargin \linewidth
        \fi
        \noindent##1\par
      %}%
      \end{varwidth}%
      \penalty\predisplaypenalty\vskip\abovedisplayskip%
    }%
  }%
}

\MHInternalSyntaxOn
\def\shortintertext@measuring#1{% see \MT_shortintertext:n in mathtools
  \ifvmode\else\\\@empty\fi
  \noalign{%
    \penalty\postdisplaypenalty\vskip\abovedisplayshortskip
    \vskip-\lineskiplimit
    \vskip\normallineskiplimit
    \vskip\l_MT_above_shortintertext_sep
    %\vbox{%
    \begin{varwidth}{\linewidth}%
      \normalbaselines
      \if_dim:w
        \if_dim:w \@totalleftmargin=\z@
          \linewidth
        \else:
          -\maxdimen
        \fi:
        =\columnwidth
      \else:
        \parshape\@ne \@totalleftmargin \linewidth
      \fi:
      \noindent#1\par
    %}%
    \end{varwidth}%
    \penalty\predisplaypenalty\vskip\abovedisplayshortskip%
    \vskip-\lineskiplimit
    \vskip\normallineskiplimit
    \vskip\l_MT_below_shortintertext_sep
  }%
}
\MHInternalSyntaxOff

Then, the redefinitions commands:

\let\shortintertext\shortintertext@measuring
\let\intertext@\intertext@measuring

The measurement of the example is now improved:

Result

Full example (just the example from the question with the added code from this answer):

\documentclass[fleqn]{article}
\usepackage{etoolbox}
\usepackage{mathtools}
\usepackage{varwidth}

\usepackage{printlen}
\uselengthunit{mm}

\makeatletter

\def\intertext@measuring{% see \intertext@ in amsmath
  \def\intertext##1{%
    \ifvmode\else\\\@empty\fi
    \noalign{%
      \penalty\postdisplaypenalty\vskip\belowdisplayskip
      %\vbox{
      \begin{varwidth}{\linewidth}%
        \normalbaselines
        \ifdim\linewidth=\columnwidth
        \else \parshape\@ne \@totalleftmargin \linewidth
        \fi
        \noindent##1\par
      %}%
      \end{varwidth}%
      \penalty\predisplaypenalty\vskip\abovedisplayskip%
    }%
  }%
}

\MHInternalSyntaxOn
\def\shortintertext@measuring#1{% see \MT_shortintertext:n in mathtools
  \ifvmode\else\\\@empty\fi
  \noalign{%
    \penalty\postdisplaypenalty\vskip\abovedisplayshortskip
    \vskip-\lineskiplimit
    \vskip\normallineskiplimit
    \vskip\l_MT_above_shortintertext_sep
    %\vbox{%
    \begin{varwidth}{\linewidth}%
      \normalbaselines
      \if_dim:w
        \if_dim:w \@totalleftmargin=\z@
          \linewidth
        \else:
          -\maxdimen
        \fi:
        =\columnwidth
      \else:
        \parshape\@ne \@totalleftmargin \linewidth
      \fi:
      \noindent#1\par
    %}%
    \end{varwidth}%
    \penalty\predisplaypenalty\vskip\abovedisplayshortskip%
    \vskip-\lineskiplimit
    \vskip\normallineskiplimit
    \vskip\l_MT_below_shortintertext_sep
  }%
}
\MHInternalSyntaxOff

%% Fix for varwidth to work with fleqn option
%% https://tex.stackexchange.com/questions/394778/align-in-varwidth-seems-to-ignore-fleqn-option
\let\@vwid@eqmodetrue\@vwid@eqmodefalse

\newsavebox{\@IntertextSavebox}
\newlength{\@MaxIntertextWidth}
\newcommand{\MeasureIntertext}[1]{%
    \savebox{\@IntertextSavebox}{%
        \begin{varwidth}{\linewidth}
            #1%
        \end{varwidth}%
    }%
    %% Keep track of the maximum width of any \shorintertext and
    %% \intertext within this align* environment.
    \ifdim\wd\@IntertextSavebox>\@MaxIntertextWidth
        \setlength{\@MaxIntertextWidth}{\wd\@IntertextSavebox}%
    \fi
}%
\newsavebox{\@NonIntertextBox}
\newcommand{\GetNaturalVarwidth}[3]{%
    %% #1 = length to contain the width
    %% #2 = title for this test case
    %% #3 = text to measure
    \setlength{\@MaxIntertextWidth}{0pt}%
    \savebox{\@NonIntertextBox}{%
        \begin{varwidth}{\linewidth}
            %% ------------------------------------------------------ Problem Area
            %% This attempt to redefine these two seems to be ignored.
            %\let\shortintertext\MeasureIntertext
            \let\shortintertext\shortintertext@measuring
            %\let\intertext\MeasureIntertext
            \let\intertext@\intertext@measuring
            %% ------------------------------------------------------ 
            #3%
        \end{varwidth}%
    }%
    %% ------------------------------------------
    %% For debugging purposes show the box.
    \medskip\par
    \noindent%
    {\bfseries#2}%
    \par\noindent
    \fboxsep=0pt
    \fbox{%
        \usebox{\@NonIntertextBox}%
    }%
    \ifdim\wd\@IntertextSavebox>\wd\@NonIntertextBox
        \setlength{#1}{\wd\@IntertextSavebox}%
    \else
        \setlength{#1}{\wd\@NonIntertextBox}%
    \fi
    {\par\tiny Natural Width is \printlength{#1}.}%
}%
\makeatother

\newlength{\NaturalWidth}
\begin{document}
\GetNaturalVarwidth{\NaturalWidth}{Small text}{Small text}% Works

%% These two don't work, but right now am just focusing on align*
%\GetNaturalVarwidth{\NaturalWidth}{Single Display Equation}{%
%\[
%    F = ma.
%\]
%}
%
%\GetNaturalVarwidth{\NaturalWidth}{Single display equation with text}{%
%Single display equation
%\[
%    F = ma.
%\]
%and some more text.%
%}

\GetNaturalVarwidth{\NaturalWidth}{Single align*}{%
\begin{align*}
    F &= ma.
\end{align*}%
}

\GetNaturalVarwidth{\NaturalWidth}{Align* with text}{%
Famous Equations:
\begin{align*}
    F &= ma. \\
    E &= mc^2,
\end{align*}%
or at least they should be famous.
}

\GetNaturalVarwidth{\NaturalWidth}{Align* with shortintertext}{%
\begin{align*}
    F &= ma. \\
    \shortintertext{and}
    E &= mc^2,
\end{align*}%
}
This one above should be 23.42914mm.

\GetNaturalVarwidth{\NaturalWidth}{Align* with intertext}{%
\begin{align*}
    F &= ma. \\
    \intertext{with some longer intertext}
    E &= mc^2,
\end{align*}%
}
This one above should be greater than 23.42914mm 
(which is width of just the nonintertext portion).

\end{document}
  • Can you pleasepost a fully compilable MWE as I am having difficluty getting this to run. I get Undefined control sequence \shortintertext ...th }\normalbaselines \if_dim:w. With just \let\intertext@\intertext@measuring I get Package amsmath Error: Invalid use of \shortintertext. and with just \let\shortintertext\shortintertext@measuring I get identical results as my MWE. – Peter Grill Feb 23 '18 at 6:30
  • Also, for handling the single equation environment (commented test cases above) shodul I post a separate question or is there an easy fix to those with this code? – Peter Grill Feb 23 '18 at 6:31
  • @PeterGrill Full example added (quite long, therefore I had omitted it). – Heiko Oberdiek Feb 23 '18 at 6:51
  • Hmmm, I have the same problem as before Undefined control sequence: shortintertext ...th }\normalbaselines \if_dim:w. I just updated all packages and saw that etoolbox v2.5e was new, but it sill fails. Have added output of \listfiles to the question. – Peter Grill Feb 23 '18 at 7:33
  • 1
    Finally got to the bottom of the problem here. It appears that somehow an older (2016 or earlier) mathtools package was used when you ran this MWE. The \if_dim no longer exists. The macros in mathtools in TeXLive2017 are prefixed with \MH_. – Peter Grill Mar 25 '18 at 7:26

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.