1

I'd like to wrap the proof environment to add bars on the left (the \tcolorbox package does not handle foot notes properly). However, when I do the wrapping I get unwanted space before and after the proof:

enter image description here

while tcolorbox does the wrapping correctly (except that it does not handle footnotes properly):

enter image description here

What is the proper way to remove the space before and after the environment proof, and add it back before/after my wrapping?

MWE

\documentclass{article}
\RequirePackage{tikz}
\usetikzlibrary{calc,tikzmark}
\usepackage{amsmath}
\usepackage{amsthm}
\usepackage{changepage}
% To show that tcolorbox has no troubles to wrap:
\RequirePackage[many]{tcolorbox}
\newenvironment{prooftcolor}{\begin{proof}}{\end{proof}}
\tcolorboxenvironment{prooftcolor}{
  blanker,
  before skip=\topsep,
  after skip=\topsep,
  borderline west={0.4pt}{0.4pt}{black},
  breakable,
  left=2.5mm,
  grow to left by=2.5mm,
}
\usepackage{hyperref}
\usepackage{lipsum}
\begin{document}

\section{Version adjustwidth}
\lipsum[1]

\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%
}


\begin{adjustwidth}{0mm}{0mm}
  \addZeroWidthLine{\tikzmark{A}}%
  {\begin{proof}
    Hello
  \end{proof} \nobreak} % nobreak is used to avoid a new page between proof and tikzmark.
  \addZeroWidthLine{\tikzmark{B}}
\end{adjustwidth}
\tikz[remember picture, overlay] \draw (pic cs:A) -- (pic cs:B);


\section{Version tcolorbox}

\begin{prooftcolor}%
  Hello\footnote{Hello.}
  Blablabla.
\end{prooftcolor}


\end{document}

UPDATE

To answer to egreg, I may not have been clear enough, but I don't want to use anymore tcolorbox (because it poorly handles footnotes), I just want to fake it. So here is a new MWE that does not use tcolorbox at all. For now I can fake the desired look using [yshift=-2.5mm]:

enter image description here

If I don't use this shift, I get a line which is too high (it starts before the space instead of after), which I don't want:

enter image description here

However, hardcoding the shift gives bad results if the text has some height (the top of the box is not aligned anymore with the line), and I expect other breakages, for instance if the space at the top of a page is not the same…

enter image description here

That's why I'm wondering if there is a generic way to move space from before the function to after. I tried the solution of egreg, but it seems that the space is added inside \trivlist, so this does not solve my problem. Ideally, I'd like the solution to work for any environment: \tcolorbox seems to be able to wrap any environment so I guess there should be a way to do that.

\documentclass{article}
\RequirePackage{tikz}
\usetikzlibrary{calc,tikzmark}
\usepackage{amsmath}
\usepackage{amsthm}
\usepackage{changepage}
\usepackage{lipsum}

\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%
}

\newenvironment{prooftest}{%
  \begin{adjustwidth}{-2.5mm}{0mm}%
    \addZeroWidthLine{\tikzmark{A}}% Adds a marker before the proof
    \begin{adjustwidth}{2.5mm}{0mm}%
      \begin{proof}%
  }{%
      \end{proof} % nobreak is used to avoid a new page between proof and tikzmark.
      \addZeroWidthLine{\tikzmark{B}\tikz[remember picture, overlay] \draw[line width=.2pt] ([yshift=-2.5mm]{pic cs:A}) -- ({pic cs:B}-|{pic cs:A});}%
    \end{adjustwidth}%
  \end{adjustwidth}
}


\begin{document}

\section{Version adjustwidth}
\lipsum[1]

\begin{prooftest} %
  Try %\rule[-5mm]{2cm}{2cm}
  to uncomment the rule to see how bad it is to hardcode values.
\end{prooftest}

\lipsum[1]

\end{document}

UPDATE

Thanks a lot for your answer egreg, but as far as I see this still does not handle properly the height of the line: the height is not the one of the text but of the "proof" text in your example.

enter image description here

My above example was actually closer to what I wanted, it's just that if you look carefully you'll see that the top part of the rule is not exactly aligned with the line on the left (it's a bit above it). Ok, I'm maybe a bit nit-picking, but I was more generally curious to know if there are general methods to remove the space of an environment without manually copy/pasting this environment and removing the space where it appears (tcolorbox seems to have an automatic procedure to do that, I don't think it has a different specification for each environment).

UPDATE

The above solution was not always working, for instance here is an issue with theorems:

enter image description here

\documentclass{article}
\RequirePackage{tikz}
\usetikzlibrary{calc,tikzmark}
\usepackage{amsmath}
\usepackage{amsthm}
\usepackage{changepage}
\usepackage{lipsum}
\usepackage{thmtools} %% Improves existing theorem packages (like amsthm) and provides declaretheorem
\theoremstyle{plain} % Style, see http://www.ams.org/arc/tex/amscls/amsthdoc.pdf p. 8 for recommanded styles
\declaretheorem[name=Theorem,numberwithin=section]{theorem}

\newlength{\oldbaselineskip}
\newlength{\oldlineskip}
\newlength{\oldlineskiplimit}

%%% How to write properly this thing?
\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%
}

\newenvironment{prooftest}{%
  \begin{adjustwidth}{-2.5mm}{0mm}%
    \addZeroWidthLine{\tikzmark{A}}% Adds a marker before the proof
    \begin{adjustwidth}{2.5mm}{0mm}%
      \begin{proof}%
  }{%
      \end{proof} % nobreak is used to avoid a new page between proof and tikzmark.
      \addZeroWidthLine{\tikzmark{B}\tikz[remember picture, overlay] \draw[line width=.2pt] ([yshift=-2.5mm]{pic cs:A}) -- ({pic cs:B}-|{pic cs:A});}%
    \end{adjustwidth}%
  \end{adjustwidth}
}


\begin{document}

\section{Version adjustwidth}
\lipsum[1]

\begin{theorem}
  Hello
\end{theorem}

\begin{prooftest} %
  Try \rule[-5mm]{2cm}{2cm}
  to uncomment the rule to see how bad it is to hardcode values.
\end{prooftest}

\lipsum[1]

\end{document}

However I read here Why does a parbox of height zero consume vertical space? that \nointerlineskip could help to remove spacing. And I tried to put \nointerlineskip at two positions, and indeed it helps, but we still need to modify baselineskip and friends.

enter image description here

Not sure if it's the proper way to remove space, nor how resilient it is, or if there are more proper solutions, so far it looks a bit like cooking...

% https://tex.stackexchange.com/questions/532948/robustly-add-a-border-to-the-left-of-a-text-spanning-several-pages
\documentclass[a4paper,12pt]{memoir}
\usepackage{lipsum}
\usepackage{amsthm}
\usepackage{tikz}
\usetikzlibrary{calc,tikzmark}
\usepackage{thmtools} %% Improves existing theorem packages (like amsthm) and provides declaretheorem
\theoremstyle{plain} % Style, see http://www.ams.org/arc/tex/amscls/amsthdoc.pdf p. 8 for recommanded styles
\declaretheorem[name=Theorem,numberwithin=section]{theorem}

\newlength{\oldbaselineskip}
\newlength{\oldlineskip}
\newlength{\oldlineskiplimit}

\long\def\addZeroWidthLine#1{%
  \nointerlineskip\oldbaselineskip=\baselineskip%
  \oldlineskip=\lineskip%
  \oldlineskiplimit=\lineskiplimit%
  \baselineskip=0pt%
  \lineskip=0pt%
  \lineskiplimit=0pt%
  \noindent#1\par\nointerlineskip\nobreak%
  \baselineskip=\oldbaselineskip%
  \lineskip=\oldlineskip%
  \lineskiplimit=\oldlineskiplimit%
}

\begin{document}

\newenvironment{prooftest}{%
  \begin{adjustwidth}{-2.5mm}{0mm}%
    \addZeroWidthLine{\tikzmark{A}}% Adds a marker before the proof
    \begin{adjustwidth}{2.5mm}{0mm}%
      \begin{proof}%
  }{%
      \end{proof} % nobreak is used to avoid a new page between proof and tikzmark.
      \addZeroWidthLine{\tikzmark{B}\tikz[remember picture, overlay] \draw[line width=.2pt] ([yshift=-2.5mm]{pic cs:A}) -- ({pic cs:B}-|{pic cs:A});}%
    \end{adjustwidth}%
  \end{adjustwidth}
}

\begin{theorem}
  See that this space is large:
\end{theorem}
\begin{prooftest}~% 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$:
\end{prooftest}


\begin{theorem}
  while this one is small:
\end{theorem}
\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$:
\end{proof}

\end{document}

EDIT

Also, note that there is a function \removelastskip to... remove the last space as explained here.

7
  • apart from anything else you are adding two space tokens after the \end{proof} before the \tikzmark which makes it harder to ensure good positioning of the mark. You have % all over the code but most of them are following command names so do nothing, and ones after length literals like 0pt shouldn't be there but despite all the % elsewhere \end{proof} \nobreak} % has two explicit spaces added, Nov 25, 2021 at 23:42
  • @DavidCarlisle good catch, thanks... these spaces, I hate them. That said, I'm not sure it solves all my problems: in my local dev, I'm using ExplSyntaxOn, and I think it removes all these spaces and I've the same issues. However, I remarked that adding \begin{adjustwidth}{0mm}{0mm} around my code actually removes the space (i.e. when I remove this line, I have more space). Any idea what black magic is involved?
    – tobiasBora
    Nov 25, 2021 at 23:49
  • not really: the code seems far more complicated than needed \addZeroWidthLine for example could simply use a group rather than restoring everything (and you seem to have omitted \parskip), but it is making a paragraph so making getting the spacing right harder, you could add the tikzmark in vertical mode without generating a paragraph or better add the marks in the existing paragraph so they don't add extra vertical material. Nov 25, 2021 at 23:58
  • I'm not claiming my code is efficient, I'm not really understanding all these stuff so my approach is more a trial and error approach (I can't even find documentation for nointerlineskip) ^^ Thanks for the grouping trick, you are right. Concerning the vertical mode, that's part of the things I don't yet understand (hence this question I guess). If you have two paragraphs around a node in vertical mode, won't it create a new paragraph? Also, I can't add the mark in the existing paragraph as I want the mark to appear above the top of the line (that's why I create a new line)
    – tobiasBora
    Nov 26, 2021 at 0:03
  • the mark doesn't appear at all, it's just an invisible node, I'd put it next to the P of Proof so it never affected any space at all, getting the end of proof is harder but amsmath has already done that work to add the qedmark so I'd put the second tikzmark with that. Nov 26, 2021 at 0:14

1 Answer 1

1

The method for getting the right coordinates might be improved.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,tikzmark}
\usepackage{amsmath}
\usepackage{amsthm}
\usepackage{lipsum}

\newcounter{Proofcnt}
\newlength{\Proofht}
\newenvironment{Proof}
 {%
  \stepcounter{Proofcnt}%
  \begin{tikzproof}%
 }
 {%
  \end{tikzproof}%
 }

\newcommand{\tikzqed}{%
  \strut\openbox
  \tikzmark{B\theProofcnt}%
  \tikz[remember picture, overlay]
    \draw[line width=.2pt]
      ([xshift=-2.5mm,yshift=\Proofht]{pic cs:A\theProofcnt}) --
      ([xshift=-\the\dimexpr2.5mm+\linewidth]{pic cs:B\theProofcnt}-|{pic cs:A\theProofcnt});%
}
\makeatletter
\newenvironment{tikzproof}[1][\proofname]{\par
  \renewcommand{\qedsymbol}{\tikzqed}%
  \settoheight{\Proofht}{\proofname}%
  \pushQED{\qed}%
  \normalfont \topsep6\p@\@plus6\p@\relax%\z@skip
  \trivlist
  \item[\hskip\labelsep
        \itshape
    \tikzmark{A\theProofcnt}#1\@addpunct{.}]\ignorespaces
}{%
  \popQED\endtrivlist\@endpefalse
}
\makeatother

\begin{document}

\vspace*{\fill}

\section{No adjustwidth}

\lipsum[1][1-4]

\begin{Proof}
Test.\footnote{A note} \lipsum[2][1-4]
\end{Proof}

\lipsum[3][1-4]

\begin{Proof}
Test.\footnote{A note} \lipsum[2][1-4]
\[
a+b=c\qedhere
\]
\end{Proof}

\lipsum[3][1-4]

\end{document}

Of course this won't work if there is a page break in the proof.

enter image description here

3
  • Thanks for your answer. But maybe I was not clear enough: I don't want to use tcolorbox to add the lines, but my own solution since tcolorbox does not handle footnotes the way I want (I added a clearer (I hope?) MWE in my question). I tried to use your environment with my solution, but the space is still here.
    – tobiasBora
    Nov 22, 2021 at 13:10
  • @tobiasBora The new version doesn't use adjustwidth, but you're advised that \tikzmark doesn't work across page breaks.
    – egreg
    Nov 22, 2021 at 17:27
  • Thanks a lot for your update (+1). This is not exactly what I wanted (see my edit), but I'm maybe nitpicking a bit. Concerning the tikzmark accross page breaks, I solve that already in another post tex.stackexchange.com/questions/532948/… Also, one of the big issues of that solution (much more annoying that this precise question) is that my lines overlap footnotes. In case you have a solution for that I'd love to hear it tex.stackexchange.com/questions/623412/…
    – tobiasBora
    Nov 22, 2021 at 18:17

You must log in to answer this question.

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