0

This is a continuation of this question. Using \nowidow, page breaking of the mindflow environments works fine when there's only pure text inside:

\documentclass[mathlines]{article}
\usepackage[a4paper]{geometry}

\usepackage{mindflow}
\mindflowset{linenumber,rightmarker}

\usepackage{blindtext}

\begin{document}

\blindtext[5]

%% nowidow works fine
\begin{mindflow}
    \blindtext
    More text
\end{mindflow}

\end{document}

pure text

However, when the environment is ended with a displayed equation, \nowidow doesn't seem to work well. Here is an example:

\documentclass[mathlines]{article}
\usepackage[a4paper]{geometry}

\usepackage{mindflow}
\mindflowset{linenumber,rightmarker}

\usepackage{blindtext}

\begin{document}

\blindtext[5]

%% Not working
\begin{mindflow}
    \blindtext
    \[a+b=c\]
    % More text
\end{mindflow}

\end{document}

displayed math

How can I fix this behavior?


Below is the current version of mindflow.sty:

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{mindflow}
    [2021/05/25 mindflow environment]
\RequirePackage{kvoptions}
\SetupKeyvalOptions{%
    family = @mindflow,
    prefix = @mindflow@
}
\DeclareBoolOption[true]{on}               % Turn on mindflow
\DeclareBoolOption[false]{off}             % Turn off mindflow
\DeclareBoolOption[false]{leftmarker}      % Left marker
\DeclareBoolOption[false]{rightmarker}     % Right marker
\DeclareBoolOption[false]{linenumber}      % Left line numbers
\DeclareBoolOption[false]{leftlinenumber}  % Left line numbers
\DeclareBoolOption[false]{rightlinenumber} % Right line numbers
\DeclareBoolOption[false]{twocolumn}       % Two column
\DeclareBoolOption[false]{incolumn}        % Separation line fits in column

\ProcessKeyvalOptions*\relax

\if@mindflow@on
  \@mindflow@offfalse
\fi
\if@mindflow@twocolumn
  \@mindflow@incolumntrue
\fi
\if@mindflow@linenumber
  \@mindflow@leftlinenumbertrue
\fi

%%================================
%% Initialization
%%================================
\RequirePackage{lineno}
\RequirePackage{xcolor}

\colorlet{mfSavedColor}{.}
\colorlet{mindflowLine}{mfSavedColor!30}
\colorlet{mindflowText}{mfSavedColor!30}
\colorlet{mindflowMarker}{mfSavedColor!30}
\colorlet{mindflowNum}{mfSavedColor!8}

\newcommand{\mindflowTextFont}{\footnotesize}
\newcommand{\mindflowNumFont}{\scriptsize\ttfamily}
\newcommand{\mindflowMarkerFont}{\scriptsize\ttfamily}
\newcommand{\mindflowLeft}{*}
\newcommand{\mindflowRight}{*}
\newlength{\mindflowLineHeight}
\setlength{\mindflowLineHeight}{0.4pt}

%%================================
%% The mindflow environment
%%================================
\RequirePackage{nowidow}
\RequirePackage{verbatim}
\newif\ifLNturnsON
\newcommand*{\mfSepLine}{%
  \parskip=0pt
  \nowidow[3]\par\nobreak%
  \LNturnsONfalse%
  \ifLineNumbers\LNturnsONtrue\fi\nolinenumbers%
  \vspace*{-.5\baselineskip}%
  \if@mindflow@incolumn%
    \makebox[\linewidth]{\color{mindflowLine}\rule{\linewidth}{\mindflowLineHeight}}%
  \else%
    \hspace*{-\paperwidth}%
    \makebox[\linewidth]{\color{mindflowLine}\rule{4\paperwidth}{\mindflowLineHeight}}%
  \fi%
  \nowidow[3]\par\nobreak%
  \ifLNturnsON\linenumbers\fi%
}

\newcounter{recordLN}
\newcounter{mfLN}
\setcounter{mfLN}{1}

\let\mindflowOFF=\comment
\let\endmindflowOFF=\endcomment

\def\mindflowON{%
  \medskip%
  \setcounter{recordLN}{\value{linenumber}}%
  \setcounter{linenumber}{\value{mfLN}}%
  \LNturnsONfalse%
  \ifLineNumbers\LNturnsONtrue\fi\nolinenumbers%
  \mfSepLine%
  \normalfont\mindflowTextFont\color{mindflowText}%
  \linenumbers%
  \renewcommand{\makeLineNumber}{%
    \hss%
    \if@mindflow@leftlinenumber%
      \normalfont\mindflowNumFont\color{mindflowNum}\LineNumber\hspace{1em}%
    \fi%
    \color{mindflowMarker}%
    \if@mindflow@leftmarker%
      \normalfont\mindflowMarkerFont\mindflowLeft\hspace{1em}%
    \fi%
    \rlap{\hskip\textwidth%
      \if@mindflow@rightmarker%
        \hspace{1em}\mindflowRight%
      \fi%
      \if@mindflow@rightlinenumber%
        \hspace{1em}%
        \normalfont\mindflowNumFont\color{mindflowNum}\LineNumber%
      \fi%
    }%
  }%
}
\def\endmindflowON{%
  \mfSepLine%
  \ifLNturnsON\linenumbers\fi%
  \setcounter{mfLN}{\value{linenumber}}%
  \setcounter{linenumber}{\value{recordLN}}%
  \medskip%
}

\if@mindflow@off
  \let\mindflow=\mindflowOFF
  \let\endmindflow=\endmindflowOFF
\else
  \let\mindflow=\mindflowON
  \let\endmindflow=\endmindflowON
\fi

%%================================
%% \mindflowset
%%================================
\define@key{mindflow}{on}[true]{%
  \csname @mindflow@on#1\endcsname%
  \if@mindflow@off%
    \let\mindflow=\mindflowOFF%
    \let\endmindflow=\endmindflowOFF%
  \else%
    \let\mindflow=\mindflowON%
    \let\endmindflow=\endmindflowON%
  \fi%
}
\define@key{mindflow}{off}[true]{%
  \csname @mindflow@off#1\endcsname%
  \if@mindflow@off%
    \let\mindflow=\mindflowOFF%
    \let\endmindflow=\endmindflowOFF%
  \else%
    \let\mindflow=\mindflowON%
    \let\endmindflow=\endmindflowON%
  \fi%
}
\define@key{mindflow}{leftmarker}[true]{\csname @mindflow@leftmarker#1\endcsname}
\define@key{mindflow}{rightmarker}[true]{\csname @mindflow@rightmarker#1\endcsname}
\define@key{mindflow}{linenumber}[true]{\csname @mindflow@linenumber#1\endcsname}
\define@key{mindflow}{leftlinenumber}[true]{\csname @mindflow@leftlinenumber#1\endcsname}
\define@key{mindflow}{rightlinenumber}[true]{\csname @mindflow@rightlinenumber#1\endcsname}
\define@key{mindflow}{twocolumn}[true]{\csname @mindflow@twocolumn#1\endcsname}
\define@key{mindflow}{incolumn}[true]{\csname @mindflow@incolumn#1\endcsname}
\define@key{mindflow}{linecolor}{\colorlet{mindflowLine}{#1}}
\define@key{mindflow}{textcolor}{\colorlet{mindflowText}{#1}}
\define@key{mindflow}{numcolor}{\colorlet{mindflowNum}{#1}}
\define@key{mindflow}{markercolor}{\colorlet{mindflowMarker}{#1}}
\define@key{mindflow}{textfont}{\renewcommand{\mindflowTextFont}{#1}}
\define@key{mindflow}{numfont}{\renewcommand{\mindflowNumFont}{#1}}
\define@key{mindflow}{markerfont}{\renewcommand{\mindflowMarkerFont}{#1}}
\define@key{mindflow}{left}{\renewcommand{\mindflowLeft}{#1}}
\define@key{mindflow}{right}{\renewcommand{\mindflowRight}{#1}}
\define@key{mindflow}{lineheight}{\setlength{\mindflowLineHeight}{#1}}
\newcommand{\mindflowset}[1]{%
  \setkeys{mindflow}{#1}%
  \if@mindflow@twocolumn%
    \@mindflow@incolumntrue%
  \fi%
  \if@mindflow@linenumber%
    \@mindflow@leftlinenumbertrue%
  \fi%
}

%%================================
%% lineno patch
%%================================
\ifdefined\linenomathpatch\else
  \RequirePackage{amsmath}
  \RequirePackage{etoolbox}
  \newcommand*\linenomathpatch[1]{%
    \cspreto{#1}{\linenomath}%
    \cspreto{#1*}{\linenomath}%
    \csappto{end#1}{\endlinenomath}%
    \csappto{end#1*}{\endlinenomath}%
  }
  \newcommand*\linenomathpatchAMS[1]{%
    \cspreto{#1}{\linenomathAMS}%
    \cspreto{#1*}{\linenomathAMS}%
    \csappto{end#1}{\endlinenomath}%
    \csappto{end#1*}{\endlinenomath}%
  }
  \expandafter\ifx\linenomath\linenomathWithnumbers
    \let\linenomathAMS\linenomathWithnumbers
    \patchcmd\linenomathAMS{\advance\postdisplaypenalty\linenopenalty}{}{}{}
  \else
    \let\linenomathAMS\linenomathNonumbers
  \fi
  \linenomathpatch{equation}
  \linenomathpatchAMS{gather}
  \linenomathpatchAMS{multline}
  \linenomathpatchAMS{align}
  \linenomathpatchAMS{alignat}
  \linenomathpatchAMS{flalign}
\fi
\endinput

1 Answer 1

1

You need

\def\mindflowON{%
\postdisplaypenalty=10000
...

In an attempt to find this solution, I had to rewrite some of the code to understand it better (now I think it is more understandable, at least for me). This MWE contains the modified mindflow.sty file (certainly some aspects will need to be improved/corrected, expecially for the \linenomath... macros that I have not taken into account. I still hope it will be useful):

\begin{filecontents}[overwrite]{mindflow.sty}
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{mindflow}
    [2021/05/25 mindflow environment]
\RequirePackage{kvoptions}
\SetupKeyvalOptions{%
    family = @mindflow,
    prefix = @mindflow@
}
\DeclareBoolOption[true]{on}               % Turn on mindflow
\DeclareBoolOption[false]{off}             % Turn off mindflow
\DeclareBoolOption[false]{leftmarker}      % Left marker
\DeclareBoolOption[false]{rightmarker}     % Right marker
\DeclareBoolOption[false]{linenumber}      % Left line numbers
\DeclareBoolOption[false]{leftlinenumber}  % Left line numbers
\DeclareBoolOption[false]{rightlinenumber} % Right line numbers
\DeclareBoolOption[false]{twocolumn}       % Two column
\DeclareBoolOption[false]{incolumn}        % Separation line fits in column

\ProcessKeyvalOptions*\relax

\if@mindflow@twocolumn
  \@mindflow@incolumntrue
\fi
\if@mindflow@linenumber
  \@mindflow@leftlinenumbertrue
\fi

%%================================
%% Initialization
%%================================
\RequirePackage{lineno}
\RequirePackage{xcolor}

\colorlet{mfSavedColor}{.}
\colorlet{mindflowLine}{mfSavedColor!30}
\colorlet{mindflowText}{mfSavedColor!30}
\colorlet{mindflowMarker}{mfSavedColor!30}
\colorlet{mindflowNum}{mfSavedColor!8}

\newcommand{\mindflowTextFont}{\footnotesize}
\newcommand{\mindflowNumFont}{\scriptsize\ttfamily}
\newcommand{\mindflowMarkerFont}{\scriptsize\ttfamily}
\newcommand{\mindflowLeft}{*}
\newcommand{\mindflowRight}{*}
\newlength{\mindflowLineHeight}
\setlength{\mindflowLineHeight}{0.4pt}

%%================================
%% The mindflow environment
%%================================
\RequirePackage{nowidow}
\RequirePackage{verbatim}
\newcommand*{\mfSepLine}{%
  \if@mindflow@incolumn%
    \makebox[\linewidth]{\color{mindflowLine}\rule{\linewidth}{\mindflowLineHeight}}%
  \else%
    \hspace*{-\paperwidth}%
    \makebox[\linewidth]{\color{red}\rule{4\paperwidth}{\mindflowLineHeight}}%
  \fi%
}

\newcounter{recordLN}
\newcounter{mfLN}
\setcounter{mfLN}{1}

\if@mindflow@off
  \let\mindflow\comment
  \let\endmindflow\endcomment
\else
\newenvironment{mindflow}{
\postdisplaypenalty=10000
  \smallskip

  \parskip=0pt
  \setcounter{recordLN}{\value{linenumber}}%
  \setcounter{linenumber}{\value{mfLN}}%

  \par\nopagebreak\mfSepLine\smallskip

  \linenumbers
  \normalfont\mindflowTextFont\color{mindflowText}%
  \renewcommand{\makeLineNumber}{%
    \hss%
    \if@mindflow@leftlinenumber%
      \normalfont\mindflowNumFont\color{mindflowNum}\LineNumber\hspace{1em}%
    \fi%
    \color{mindflowMarker}%
    \if@mindflow@leftmarker%
      \normalfont\mindflowMarkerFont\mindflowLeft\hspace{1em}%
    \fi%
    \rlap{\hskip\textwidth%
      \if@mindflow@rightmarker%
        \hspace{1em}\mindflowRight%
      \fi%
      \if@mindflow@rightlinenumber%
        \hspace{1em}%
        \normalfont\mindflowNumFont\color{mindflowNum}\LineNumber%
      \fi%
    }%
  }%
}{\nowidow[3]%
  \par\nopagebreak\mfSepLine
  \nolinenumbers

  \setcounter{mfLN}{\value{linenumber}}%
  \setcounter{linenumber}{\value{recordLN}}%
  \medskip%
}
\fi

\newcommand{\mindflowset}[1]{%
  \setkeys{mindflow}{#1}%
  \if@mindflow@twocolumn%
    \@mindflow@incolumntrue%
  \fi%
  \if@mindflow@linenumber%
    \@mindflow@leftlinenumbertrue%
  \fi%
}

\define@key{mindflow}{leftmarker}[true]{\csname @mindflow@leftmarker#1\endcsname}
\define@key{mindflow}{rightmarker}[true]{\csname @mindflow@rightmarker#1\endcsname}
\define@key{mindflow}{linenumber}[true]{\csname @mindflow@linenumber#1\endcsname}
\define@key{mindflow}{leftlinenumber}[true]{\csname @mindflow@leftlinenumber#1\endcsname}
\define@key{mindflow}{rightlinenumber}[true]{\csname @mindflow@rightlinenumber#1\endcsname}
\define@key{mindflow}{twocolumn}[true]{\csname @mindflow@twocolumn#1\endcsname}
\define@key{mindflow}{incolumn}[true]{\csname @mindflow@incolumn#1\endcsname}
\define@key{mindflow}{linecolor}{\colorlet{mindflowLine}{#1}}
\define@key{mindflow}{textcolor}{\colorlet{mindflowText}{#1}}
\define@key{mindflow}{numcolor}{\colorlet{mindflowNum}{#1}}
\define@key{mindflow}{markercolor}{\colorlet{mindflowMarker}{#1}}
\define@key{mindflow}{textfont}{\renewcommand{\mindflowTextFont}{#1}}
\define@key{mindflow}{numfont}{\renewcommand{\mindflowNumFont}{#1}}
\define@key{mindflow}{markerfont}{\renewcommand{\mindflowMarkerFont}{#1}}
\define@key{mindflow}{left}{\renewcommand{\mindflowLeft}{#1}}
\define@key{mindflow}{right}{\renewcommand{\mindflowRight}{#1}}
\define@key{mindflow}{lineheight}{\setlength{\mindflowLineHeight}{#1}}

%%================================
%% lineno patch
%%================================
\ifdefined\linenomathpatch\else
  \RequirePackage{amsmath}
  \RequirePackage{etoolbox}
  \newcommand*\linenomathpatch[1]{%
    \cspreto{#1}{\linenomath}%
    \cspreto{#1*}{\linenomath}%
    \csappto{end#1}{\endlinenomath}%
    \csappto{end#1*}{\endlinenomath}%
  }
  \newcommand*\linenomathpatchAMS[1]{%
    \cspreto{#1}{\linenomathAMS}%
    \cspreto{#1*}{\linenomathAMS}%
    \csappto{end#1}{\endlinenomath}%
    \csappto{end#1*}{\endlinenomath}%
  }
  \expandafter\ifx\linenomath\linenomathWithnumbers
    \let\linenomathAMS\linenomathWithnumbers
    \patchcmd\linenomathAMS{\advance\postdisplaypenalty\linenopenalty}{}{}{}
  \else
    \let\linenomathAMS\linenomathNonumbers
  \fi
  \linenomathpatch{equation}
  \linenomathpatchAMS{gather}
  \linenomathpatchAMS{multline}
  \linenomathpatchAMS{align}
  \linenomathpatchAMS{alignat}
  \linenomathpatchAMS{flalign}
\fi
\endinput
\end{filecontents}


\documentclass[mathlines]{article}
\usepackage[a4paper]{geometry}

\usepackage[on]{mindflow}
\mindflowset{linenumber,rightmarker}

\usepackage{blindtext}

\begin{document}

\blindtext[5]

\begin{mindflow}
\blindtext
    \[a+b=c\]
    % More text
\end{mindflow}
\blindtext

\clearpage
\blindtext[5]
\begin{mindflow}
\blindtext
%    More text%
\end{mindflow}
\blindtext

\end{document}

enter image description here

6
  • Thank you, your code does seem much clearer than mine. Later I will consider moving some of the code from \mfSepLine to \mindflowOn and \endmindflowOn.
    – Jinwen
    Commented May 25, 2021 at 14:09
  • Just a little curious, why doesn't the original \nopagebreak work but instead \nobreak? And how did you know about things like \postdisplaypenalty, \relpenalty and \binoppenalty? They look quite mysterious to me.
    – Jinwen
    Commented May 25, 2021 at 14:16
  • 1) Please ignore \relpenalty and \binoppenalty. They are irrelevant to this specific code. (I edited the answer.) 2) You can find the definition of \nobreak in the latex.ltx file: \def\nobreak{\penalty \@M} which equals to \penalty10000, as well as the def. of \nopagebreak. As suggested by @egreg here: tex.stackexchange.com/a/94219/231952, you should use \nopagebreak in those cases where the purpose is clear. (I have corrected the answer for this aspect as well.) 3) I only became aware of the commands \postdisplaypenalty, \relpenalty, and \binoppenalty today.
    – Ivan
    Commented May 25, 2021 at 14:46
  • There is another problem: the code above solves the issue of the bottom line with \nowidow, but there's also the issue of the top line (left on the last page alone) which requires \noclub, where should it be inserted? I tried several places but none of them work.
    – Jinwen
    Commented May 25, 2021 at 14:54
  • 1
    I can not find a solution for clubs. I suggest you an alternative route: \usepackage{tcolorbox} \tcbuselibrary{breakable} \newtcolorbox{mindflow}{breakable,colback=white,colframe=gray, leftrule=0pt, rightrule=0pt, toprule=1pt, bottomrule=1pt, sharp corners,grow to left by=5cm,left=5cm,grow to right by=5cm,right=5cm,fontupper=\color{gray}} and for numbering: \begin{internallinenumbers} \end{internallinenumbers}
    – Ivan
    Commented May 25, 2021 at 18:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .