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}
\qedhere
in 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.subproof
definition effectively inserts a\par
before 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\qedhere
is an appropriate remedy for every proof with asubproof
.amsthm
tag since that's where\qedhere
is defined.