7

I would like to add a border to the left of some indented text, eventually spanning several pages and nested. My goal is similar to Indentation level inside proof but the solution I found back that time was not working on text spanning several pages. For what I tried, mdframed and tcolorbox have issues with nested boxes spanning several pages (for example the inner box starts on a new page).

Meanwhile, I found the command adjustwith that let me indent my text in a pretty simple and robust way. But I still don't know how to add a vertical line to the left of the text.

Here is what I want:

enter image description here

And what I have so far:

enter image description here

MWE:

\documentclass{article}
\usepackage{changepage}% http://ctan.org/pkg/changepage
\usepackage{lipsum}% http://ctan.org/pkg/lipsum

\newenvironment{subproof}{\begin{adjustwidth}{2.5em}{0pt}}{\end{adjustwidth}}

\begin{document}
\section{Title}
I would like to add a black border on the left of all ``adjustwidth'' blocks:
\begin{subproof}
  \lipsum[1]
  \begin{subproof}
    \lipsum[1-2]
    \[\Delta = b^2 - 4ac\]
    \lipsum[1-2]
  \end{subproof}
  \lipsum[1]
\end{subproof}
\lipsum[1]
\end{document}

EDIT: I just heard of the changebar package, and it does something quite close to the thing I want... except that I can't find how to change the position of the line several times. Indeed, if I change \changebarsep after the beginning of the document, the lines position are not changed... I was thinking to modify the package to my need, but I'm not sure to see yet how to do...

EDIT2:

The proposition of muzimuzhi does not work, because when the nested subproof is larger than a page, it it moved to the next page (leaving a bit blank in the first page), and the bars are a bit ugly as on the next page the inner bars are longer than the outer bars:

enter image description here

Code to produce this result:

\documentclass{article}
\usepackage{lipsum}
\usepackage{tcolorbox}
\tcbuselibrary{breakable, skins}

\newtcolorbox{lmarginbox}{
  blanker, breakable, left=2.5em,
  borderline west={1pt}{0pt}{black}}

\begin{document}
\lipsum[33]

\begin{lmarginbox}
  \lipsum[1-2]
  \begin{lmarginbox}
    \lipsum[1-5]
  \end{lmarginbox}
  \lipsum[4-5]
\end{lmarginbox}

\lipsum[33]
\end{document}

-- EDIT 3 --

I found also this answer which seems to provide some tricks to draw lines between several pages using tikz. I guess it could be a solution...

1
  • 1
    "For what I tried, [...] tcolorbox have issues with [breakable] nested boxes ". IMHO, expand a box more than one page is a bad idea, nest boxes is a bad idea, and both things together is a dreadful idea, but it is possible with tcolorbox.
    – Fran
    Commented Apr 25, 2021 at 17:19

3 Answers 3

2

Ok, so I managed to have a first version which works quite nicely, including in memoir with content positioned differently on odd and even pages.

enter image description here

% 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{tikzpagenodes}
\usetikzlibrary{calc,tikzmark}
\usepackage{lipsum}
%\usepackage{showframe}
\usepackage{everypage}
\usepackage{changepage}
\usepackage{environ}

\def\subproofsDefaultShift{7mm}

\tikzset{
  /subproofs/defaultStyle/.style={
    black!30!white,
    line width=1pt,
    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] (pic cs:beginTikzmark#1) to ({pic cs:endTikzmark#1}-|{pic cs:beginTikzmark#1});%
}

\def\drawLinesOfTikzmarkStart#1{%
  \tikz[remember picture, overlay]%
  \draw[/subproofs/defaultStyle] (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=(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%
  \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. TODO
    \addZeroWidthLine{\addTikzmarkAndPagesInfo{\thenextMarkId}}%
    \stepcounter{nextMarkId}%
    % Ensures a group is inserted around the BODY
    { \noindent \BODY \par }%
    \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}%
    }%
    {%%%%%%%%%% The end is on the same page
      \drawLinesOfTikzmarkSamePage{#1}%
    }{% 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}%
    }%
    {%%%%%%%%%% The end is on the same page
      \drawLinesOfTikzmarkEnd{#1}%
    }{%%%%%%%%%% 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}
  }
}

\AddEverypageHook{\dealWithAllLines:N{}}

\ExplSyntaxOff

\begin{document}

\newpage

\thispagestyle{empty}

\lipsum[1]

\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, there is an ugly space just above.
    \begin{subproof}
      Also the line adapts to height and depth \rule[-1cm]{2cm}{3cm}.
    \end{subproof}%
    This error is also present at the end of this subproof. \lipsum[1-3]
  \end{subproof}%
\end{subproof}

\end{document}

UPDATE

Here is a version where I also provide two environments linedproof and prooftcolorbox to also add a line on the left of the whole proof (each version puts the line at a different position).

linedproof: enter image description here

prooftcolorbox:

enter image description here

Note that prooftcolorbox is based on tcolorbox (it's not a problem because I don't nest them since subproofs is not based on tcolorbox). However it means that the border of the whole proof is not using the tikz style... which is a bit sad. I tried to write my own without tcolorbox but I have issues with spacing.

% 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}
% \directlua{ require("drawboxes")}
% \usepackage{graphicx,atbegshi}
\usepackage[many]{tcolorbox}
\usepackage{xpatch}


%\AtBeginShipout {\directlua{drawboxes.visual_debug()}}

\def\subproofsDefaultShift{5mm}
% Shift towards the center of the line
\def\subproofsDefaultFirstPointYShift{.3em} %% Better results when using baselineskip
%\def\subproofsDefaultFirstPointYShift{0em} %% Better results when using `\hrule height0pt`
\def\subproofsDefaultSecondPointYShift{0em}
\definecolor{dark-gray}{gray}{0.70}
\def\colorFrame{dark-gray}

\tikzset{
  /subproofs/defaultStyle/.style={
    \colorFrame,%black!30!white,
    line width=.4pt,
    transform canvas={xshift=-\subproofsDefaultShift/2},
  }
}

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

%%%% Uncomment to have the "baselinemode" (and comment next definition)
\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%
}

%%%% Uncomment to have the "hrule" version:
% \long\def\addZeroWidthLine#1{%
%   \vskip\lineskip\hrule height0pt\noindent#1\hrule height0pt\vskip\lineskip%
% }


\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}% nobreak is used to ensure the tikzmark is not pushed on a new page.
    \addZeroWidthLine{\tikzmark{endTikzmark\thisMarkId}}\nopagebreak%
  \end{adjustwidth}%
}%

\NewEnviron{linedproof}{%
  \edef\thisMarkId{\thenextMarkId}% Temporary variable to use at the end.
  \seq_gput_right:NV \l_ListOfLinesToDraw_seq \thisMarkId % Add it to the list
  \begin{proof}\phantom{x}% Not sure why, using ~ does not work.
    \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 }% nobreak is used to ensure the tikzmark is not pushed on a new page.
      % \hrule height0pt also "fake" a zero-width line.
    \qedhere\hrule height0pt\tikzmark{endTikzmark\thisMarkId}\end{adjustwidth}%%
  \end{proof}
}%

% \NewEnviron{wholelinedproof}{%
%   A\addZeroWidthLine{\addTikzmarkAndPagesInfo{\thenextMarkId}}B%
%   %\vskip\lineskip\noindent \hrule height0pt\addTikzmarkAndPagesInfo{\thenextMarkId}\hrule height0pt%
%   \edef\thisMarkId{\thenextMarkId}% Temporary variable to use at the end.
%   \seq_gput_right:NV \l_ListOfLinesToDraw_seq \thisMarkId % Add it to the list
%   \dealWithOneLine:V{\thisMarkId}% Draw the line for the current one.
%   \begin{proof}%
%       \stepcounter{nextMarkId}%
%       % Ensures a group is inserted around the BODY
%       { \noindent \BODY }% nobreak is used to ensure the tikzmark is not pushed on a new page.
%       % \hrule height0pt also "fake" a zero-width line.
%     \qedhere\hrule height0pt\tikzmark{endTikzmark\thisMarkId}%%
%   \end{proof}
% }%

% \NewEnviron{wholelinedproof}{%
%   \addTikzmarkAndPagesInfo{\thenextMarkId}%
%   %\vskip\lineskip\noindent \hrule height0pt\addTikzmarkAndPagesInfo{\thenextMarkId}\hrule height0pt%
%   \edef\thisMarkId{\thenextMarkId}% Temporary variable to use at the end.
%   \seq_gput_right:NV \l_ListOfLinesToDraw_seq \thisMarkId % Add it to the list
%   \dealWithOneLine:V{\thisMarkId}% Draw the line for the current one.
%   \begin{proof}%
%       \stepcounter{nextMarkId}%
%       % Ensures a group is inserted around the BODY
%       { \noindent \BODY }% nobreak is used to ensure the tikzmark is not pushed on a new page.
%       % \hrule height0pt also "fake" a zero-width line.
%     \qedhere\hrule height0pt\tikzmark{endTikzmark\thisMarkId}%%
%   \end{proof}
% }%

\ExplSyntaxOff %tcolorbox does not like explsyntax

% https://tex.stackexchange.com/questions/169794/outer-margin-of-tcolorbox
\newenvironment{prooftcolorbox}{\begin{proof}}{\end{proof}}
\tcolorboxenvironment{prooftcolorbox}{
  blanker,
  before skip=\topsep,
  after skip=\topsep,
  borderline west={0.4pt}{0.4pt}{\colorFrame},
  breakable,
  left=\subproofsDefaultShift/2,
  grow to left by=\subproofsDefaultShift/2,
%  colframe=,
%  right=12pt, % I'd avoid this
}

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


% \begin{subproof}
%   ABC
% \end{subproof}

\begin{linedproof}~% 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-5]
      Bla bla bla bla blaBla bla bla bla blaBla bla bla bla blaBla bla bla bla blaBla bla bla bla blaBla bla bla biblobi blabla blabla Bla bla bla bla blaBla bla bla bla blaBla bla bla% If this is the last thing, use \qedhere so that the qed is on the same line as this text.
    \end{subproof}%
  Which concludes the proof. Which concludes the proofWhich concludes the proofWhich concludes the proofWhich the proof. Which concludes the proof. Which concludes the proofWhich concludes the proof.
\end{linedproof}

Hello

\begin{subproof}
  Coucou
\end{subproof}

\newpage

\lipsum[1]
\begin{prooftcolorbox} We prove now that $1+1+1 = 3$. First we will prove that the equation $1+1+1=3$ is true:
    \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-5]
      Bla bla bla bla blaBla bla bla bla blaBla bla bla bla blaBla bla bla bla blaBla bla bla bla blaBla bla bla biblobi blabla blabla Bla bla bla bla blaBla bla bla bla blaBla bla bla\qedhere
    \end{subproof}%
\end{prooftcolorbox}

\newpage

Check alignement of tcolorbox proof:

Normal proofs
\begin{proof} Here is my proof.
\end{proof}

\begin{proof} Here is my proof.
\end{proof}

\begin{proof} Here is my proof.
\end{proof}

Tcolorbox proof
\begin{prooftcolorbox} Here is my proof.
\end{prooftcolorbox}

\begin{prooftcolorbox} Here is my proof.
\end{prooftcolorbox}

\begin{prooftcolorbox} Here is my proof.
\end{prooftcolorbox}



Normal proofs
\begin{proof}~

  Here is my proof.
\end{proof}

\begin{proof}~

  Here is my proof.
\end{proof}

\begin{proof}~

  Here is my proof.
\end{proof}

Lined proofs
\begin{linedproof} Here is my proof.
\end{linedproof}

\begin{linedproof} Here is my proof.
\end{linedproof}

\begin{linedproof} Here is my proof.
\end{linedproof}

\end{document}

EDIT Related: Remove space before and after proof environment

EDIT I managed to get a version handling also footnotes. See here.

1

A tcolorbox attempt

\documentclass{article}
\usepackage{lipsum}
\usepackage{tcolorbox}
\tcbuselibrary{breakable, skins}

\newtcolorbox{lmarginbox}{
  blanker, breakable, left=2.5em,
  borderline west={1pt}{0pt}{black}}

\begin{document}
\lipsum[33]

\begin{lmarginbox}
  \lipsum[1-2]
  \begin{lmarginbox}
    \lipsum[3]
  \end{lmarginbox}
  \lipsum[4-5]
\end{lmarginbox}

\lipsum[33]
\end{document}

Noticed that you use an environment name subproof. If you want to redefine a theorem-like environment, see examples in tcolorbox's documentation, sec. 17.4.

2
  • Thanks, but this solution does not work because when the nested lmarginbox goes to the next page, it it moved to the next page. See my edit for a screenshot.
    – tobiasBora
    Commented Mar 24, 2020 at 10:52
  • @tobiasBora Ah yes. tcolorbox cannot handle nested breakable boxes well. See Breakable nested tcolorbox. Commented Mar 24, 2020 at 12:52
1

I cannot regard this as a good idea, but it is possible with tcolorbox:

mwe

\documentclass[a5paper]{article}
\usepackage{lipsum}
\usepackage[most]{tcolorbox}
\newtcolorbox{badbox}{blanker, enforce breakable, left=2em,
  borderline west={1pt}{0pt}{black}}
\begin{document}
\begin{badbox}
\lipsum[1][1-8]
\begin{badbox}
\lipsum[1][1-8]
\begin{badbox}
\lipsum[1][1-8]
\begin{badbox}
\lipsum[1][1-1]
\begin{badbox}
\lipsum[1][1-2]
\begin{badbox}
\lipsum[1][1-3]
\end{badbox}
\end{badbox}
\end{badbox}
\end{badbox}
\end{badbox}
\end{badbox}
\end{document}
1
  • Thanks but it's not what I expect because it's pushing the level 3 on the next page: I want to ensure that text stays on main page until it's really necessary to move it to another page.
    – tobiasBora
    Commented Apr 25, 2021 at 18:13

You must log in to answer this question.

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