I'd like to forbid the \qed symbol to go on the next page in a proof, as the result is ugly:
Any idea how I could solve the problem, ideally by only modifying the proof and/or subproof environments? (I don't want to manually insert \qed).
Thanks!
MWE
% https://tex.stackexchange.com/questions/532948/robustly-add-a-border-to-the-left-of-a-text-spanning-several-pages
\documentclass[a4paper,12pt]{memoir}
\usepackage{amsmath}
\usepackage{amsthm}
\usepackage{tikzpagenodes}
\usetikzlibrary{calc,tikzmark}
\usepackage{lipsum}
%\usepackage{showframe}
\usepackage{everypage}
\usepackage{changepage}
\usepackage{environ}
\newlength{\oldbaselineskip}
\newlength{\oldlineskip}
\newlength{\oldlineskiplimit}
\long\def\addZeroWidthLine#1{%
\oldbaselineskip=\baselineskip%
\oldlineskip=\lineskip%
\oldlineskiplimit=\lineskiplimit%
\baselineskip=0pt%
\lineskip=0pt%
\lineskiplimit=0pt%
\noindent#1\par\nobreak%
\baselineskip=\oldbaselineskip%
\lineskip=\oldlineskip%
\lineskiplimit=\oldlineskiplimit%
}
\NewEnviron{subproof}{%
\begin{adjustwidth}{1cm}{0cm}%
\addZeroWidthLine{\tikzmark{Hello0}}%
% Ensures a group is inserted around the BODY
{ \noindent \BODY \par\nobreak }% nobreak is used to ensure the tikzmark is not pushed on a new page.
\addZeroWidthLine{\tikzmark{Bye0}}%
\tikz[remember picture, overlay] \draw ([xshift=-5mm]pic cs:Hello0) -- ([xshift=-5mm]pic cs:Bye0);
\end{adjustwidth}%
}%
\begin{document}
\thispagestyle{empty}
\begin{proof}~% Use '~' to ensure the subproof starts on a new line.
\begin{subproof}
\lipsum[1-3]
Bla bla bla bla Bla bla bla bla Bla bla bla bla Bla bla bla bla Bla bla bla bla Bla bla bla bla Bla bla bla bla Bla bla bla bla Bla bla bla bla Bla bla bla bla Bla bla bla bla Bla bla bla bla Bla bla bla bla
Bla bla bla bla Bla bla bla bla Bla bla bla bla Bla bla bla bla Bla bla bla bla Bla bla bla bla Bla bla bla
\end{subproof}
\end{proof}
\end{document}
In case you want a more complete example (the above has been simplified as much as possible):
% https://tex.stackexchange.com/questions/532948/robustly-add-a-border-to-the-left-of-a-text-spanning-several-pages
\documentclass[a4paper,12pt]{memoir}
\usepackage{amsmath}
\usepackage{amsthm}
\usepackage{tikzpagenodes}
\usetikzlibrary{calc,tikzmark}
\usepackage{lipsum}
%\usepackage{showframe}
\usepackage{everypage}
\usepackage{changepage}
\usepackage{environ}
\def\subproofsDefaultShift{5mm}
% Shift towards the center of the line
\def\subproofsDefaultFirstPointYShift{.3em}
\def\subproofsDefaultSecondPointYShift{0em}
\tikzset{
/subproofs/defaultStyle/.style={
black!30!white,
line width=.4pt,
transform canvas={xshift=-\subproofsDefaultShift/2-.5pt},
}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Deal with drawings and marking.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Warning: tikz does not like ExplSyntax since it removes spaces
\def\addTikzmarkAndPagesInfo#1{%
\tikzmark{beginTikzmark#1}%
\tikz[remember picture, overlay] \coordinate (pageInfoNWOf#1) at (current page text area.north west);%
\tikz[remember picture, overlay] \coordinate (pageInfoSEOf#1) at (current page text area.south east);%
}
\def\drawLinesOfTikzmarkSamePage#1{%
\tikz[remember picture, overlay]%
\draw[/subproofs/defaultStyle] ([yshift=-\subproofsDefaultFirstPointYShift]pic cs:beginTikzmark#1) to ([yshift=\subproofsDefaultSecondPointYShift]{{pic cs:endTikzmark#1}-|{pic cs:beginTikzmark#1}});%
}
\def\drawLinesOfTikzmarkStart#1{%
\tikz[remember picture, overlay]%
\draw[/subproofs/defaultStyle] ([yshift=-\subproofsDefaultFirstPointYShift]pic cs:beginTikzmark#1) to ({pic cs:beginTikzmark#1}|-{current page text area.south west});%
}
\def\drawLinesOfTikzmarkMiddle#1{%
\tikz[remember picture,overlay] \draw[/subproofs/defaultStyle] %
let%
\p1=(pic cs:beginTikzmark#1),%
\p2=(pageInfoNWOf#1),%
\p3=(current page text area.north west),%
\p4=(current page text area.south east) in%
(\x1-\x2+\x3,\y3) to (\x1-\x2+\x3,\y4);%
}
\def\drawLinesOfTikzmarkEnd#1{%
\tikz[remember picture,overlay] \draw[/subproofs/defaultStyle] %
let%
\p1=(pic cs:beginTikzmark#1),%
\p2=(pageInfoNWOf#1),%
\p3=(current page text area.north west),%
\p4=(current page text area.south east),%
\p5=([yshift=\subproofsDefaultSecondPointYShift]pic cs:endTikzmark#1) in %
(\x1-\x2+\x3,\y3) to (\x1-\x2+\x3,\y5);%
}
\makeatletter
% \checkmarkpage{label}{if before}{if same page}{if after}
% Apply different codes if we are on a page before, the current page,
\newcommand{\checkmarkpage}[4]% #1 = tikzmark label, #2 = less, #3 = equal, #4 = greater
{@ifundefined{save@pt@#1}{#2}{%
\edef\markid{\csname save@pt@#1\endcsname}%
\edef\markpage{\csname save@pg@\markid\endcsname}%
\ifnum\thepage<\markpage\relax #2%
\else
\ifnum\thepage=\markpage\relax #3%
\else #4%
\fi
\fi}%
}
\makeatother
%%% Starts expl3 syntax https://mirrors.concertpass.com/tex-archive/macros/latex/contrib/l3kernel/expl3.pdf
%%% For the list of modules and everything http://linorg.usp.br/CTAN/macros/latex/contrib/l3kernel/interface3.pdf
%%% (this also provides a quickstart at the beginning)
%%% For functions https://tex.stackexchange.com/questions/492794/how-to-define-two-expl3-functions-with-the-same-base-name-and-different-signatur
%%% This code is certainly not an example of LaTeX programming as it's the first time I use expl3...
\ExplSyntaxOn
% l=local, name, type. Note that this is only convention, it could be named "\foo" instead.
% clist are list separated by commas.
% To remove stuff https://tex.stackexchange.com/questions/5754/delete-an-element-from-a-comma-delimited-list
\seq_new:N\l_ListOfLinesToDraw_seq{}
\newcounter{nextMarkId}
% Inspired by https://tex.stackexchange.com/questions/528774/excess-vertical-space-in-vdots/528775#528775
% See also https://tex.stackexchange.com/questions/622881/align-element-tikzmark-with-top-of-the-current-line-instead-of-baseline/622936#622936
% TODO: Read also https://fr.overleaf.com/learn/latex/Articles/Boxes_and_Glue%3A_A_Brief%2C_but_Visual%2C_Introduction_Using_LuaTeX
\newlength{\oldbaselineskip}
\newlength{\oldlineskip}
\newlength{\oldlineskiplimit}
\long\def\addZeroWidthLine#1{%
\oldbaselineskip=\baselineskip%
\oldlineskip=\lineskip%
\oldlineskiplimit=\lineskiplimit%
\baselineskip=0pt%
\lineskip=0pt%
\lineskiplimit=0pt%
\noindent#1\par\nobreak%
\baselineskip=\oldbaselineskip%
\lineskip=\oldlineskip%
\lineskiplimit=\oldlineskiplimit%
}
\NewEnviron{subproof}{%
\edef\thisMarkId{\thenextMarkId}% Temporary variable to use at the end.
\seq_gput_right:NV \l_ListOfLinesToDraw_seq \thisMarkId % Add it to the list
\begin{adjustwidth}{\subproofsDefaultShift}{0cm}%
\dealWithOneLine:V{\thisMarkId}% Draw the line for the current one.
\addZeroWidthLine{\addTikzmarkAndPagesInfo{\thenextMarkId}}%
\stepcounter{nextMarkId}%
% Ensures a group is inserted around the BODY
{ \noindent \BODY \par\nobreak }%
\addZeroWidthLine{\tikzmark{endTikzmark\thisMarkId}}%
\end{adjustwidth}%
}%
%% Create a new function (see http://linorg.usp.br/CTAN/macros/latex/contrib/l3kernel/interface3.pdf page 14)
\cs_new:Nn \dealWithOneLine:n{
\checkmarkpage{beginTikzmark#1}{%
%%%%%%%%%% We have not yet seen the beginTikzMark... Don't care.
}{ %%%%%%%%%% We are on the page of the start.
\checkmarkpage{endTikzmark#1}%
{%%%%%%%%%% The end is later
\drawLinesOfTikzmarkStart{#1}%
%\printList:N{} Size is \seq_count:N \l_ListOfLinesToDraw_seq%
}%
{%%%%%%%%%% The end is on the same page
\drawLinesOfTikzmarkSamePage{#1}%
%% We can remove the item from the list so that we don't process it anymore.
\seq_gremove_all:Nn \l_ListOfLinesToDraw_seq {#1}%
%\printList:N{} Size is \seq_count:N \l_ListOfLinesToDraw_seq%
}{% The end was on a previous page... impossible
}%
}{ %%%%%%%%%% The start point is on a previous page
\checkmarkpage{endTikzmark#1}%
{%%%%%%%%%% The end is later
\drawLinesOfTikzmarkMiddle{#1}%
%\printList:N{} Size is \seq_count:N \l_ListOfLinesToDraw_seq%
}%
{%%%%%%%%%% The end is on the same page
\drawLinesOfTikzmarkEnd{#1}%
%% We can remove the item from the list so that we don't process it anymore.
\seq_gremove_all:Nn \l_ListOfLinesToDraw_seq {#1}%
%\printList:N{} Size is \seq_count:N \l_ListOfLinesToDraw_seq%
}{%%%%%%%%%% The end has already been seen... I don't care
}%
}%
}
% defines \dealWithOneLine:V that expands its argument
\cs_generate_variant:Nn \dealWithOneLine:n { V }
%% Create a new function (see http://linorg.usp.br/CTAN/macros/latex/contrib/l3kernel/interface3.pdf page 14)
\cs_new:Nn \dealWithAllLines:N {
\seq_map_inline:Nn \l_ListOfLinesToDraw_seq {
\dealWithOneLine:n{##1}
}
}
%% Create a new function (see http://linorg.usp.br/CTAN/macros/latex/contrib/l3kernel/interface3.pdf page 14)
\cs_new:Nn \printList:N {
[
\seq_map_inline:Nn \l_ListOfLinesToDraw_seq {
##1,
}
]
}
\AddEverypageHook{\dealWithAllLines:N{}}
\ExplSyntaxOff
\begin{document}
\newpage
\thispagestyle{empty}
\lipsum[1]
% \begin{subproof}
% ABC
% \end{subproof}
\begin{proof}~% Use '~' to ensure the subproof starts on a new line.
% See also https://tex.stackexchange.com/questions/122954/starting-a-proof-with-paragraph
\begin{subproof}%
We prove now that $1+1+1 = 3$. First we will prove that $1+1+1=3$:
\begin{subproof}%
In order to prove that $1+1+1=3$, we first prove that $1+1=2$.
\begin{subproof}%
By definition $2 = 1+1$.
\end{subproof}%
But we can show that $1+1+1=2+1$.
\begin{subproof}%
Indeed, by associativity of the addition, we know that
\begin{align}
1+1+1=(1+1)+1\label{eq:abc}
\end{align}
But we saw above that $1+1=2$ so $1+1+1=2+1$
\end{subproof}%
It is now possible to see that $1+1+1=3$
\begin{subproof}%
We can use now Eq.~\ref{eq:abc} and the definition of $3$:
[1+1+1=2+1=3]
\end{subproof}%
As you can see, the spacing issues are now solved. See \texttt{\subproofsDefaultFirstPointYShift} to move more or less the first point on the y axis (to ensure it's not too close to the above line). It defaults to \texttt{0.3em}.
\begin{subproof}
Also the line adapts to height and depth \rule[-1cm]{2cm}{3cm}.
\end{subproof}%
\lipsum[1-4]
Bla bla bla bla blaBla bla bla bla blaBla bla bla bla blaBla bla bla bla blaBla bla bla bla blaBla bla bla bla blaBla bla bla bla blaBla bla bla bla blaBla bla bla bla blaBla bla bla bla blaBla bla bla bla blaBla bla bla bla blaBla bla bla bla blaBla bla bla bla bla
\end{subproof}\nobreak%
\end{subproof}\nobreak
\end{proof}
Hello
\begin{subproof}
Coucou
\end{subproof}
\end{document}


\qedherein the last paragraph (too bad I can't find another approach, but I think it's quite fundamental especially because we usually want the qed symbol to be on the same line as the text). I'm still doing some tests. – tobiasBora Nov 18 '21 at 14:50subproofdefinition effectively inserts a\parbefore the\end{proof}. Why this is happening isn't immediately obvious to me, and I haven't the energy to trace what's happening. But even if the proof isn't near the bottom of the page, that would force the qed box onto a line by itself. So\qedhereis an appropriate remedy for every proof with asubproof. – barbara beeton Nov 18 '21 at 23:18amsthmtag since that's where\qedhereis defined. – barbara beeton Nov 18 '21 at 23:23