Drawing tikz line in the margin for multiple pages

Inspired by a code portion found on this site (I can't remember...), I could do the following to draw a line on the first page starting on top:

\documentclass[a4paper,12pt]{book}
\usepackage{tikz}
\usepackage{etoolbox}
\usepackage{lipsum}

\begin{document}

\thispagestyle{empty}

\begin{tikzpicture}[remember picture,overlay]
\node (back names) [shape=rectangle,
fill=black!80,
minimum height=\textheight,
minimum width=1cm,
anchor=north west]
\end{tikzpicture}

First line.
Second line.
\lipsum

\end{document}


What I'd like to do is to extend the rectangle to the end of a long text (so there may be an 'environment' to build and/or a newcommand with a parameter taking into account the text), and to be able to begin exactly at the begining of this text and to end exactly where it ends, even if begining or end is in the middle of the page, AND (tiebraker ;)) without using a box.

Indeed, I know how to do this using for instance mdframed and shifting to the left the left bar... It works well and it's nice but we do know that two breakable/splitable boxes created with framed, mdframed, tcolorbox, etc. can't be nested (even one with another, in the cases I tried at least). But, that's what I want to do: the line (the big rule in fact) I am drawing with tikz will be used as the container and I will be able to put other breakable/splitable boxes inside it...

EDIT: the inspiration is here: TikZ full page with absolute node positioning.

• you could put everything (including the text) inside the tikzpicture.. Then all the placement of your text can be done as you like, e.g. with nodes in different positions. – Faekynn Apr 27 '17 at 16:32
• @Faekynn I don't think that a tikzpicture will be broken across pages. – gernot Apr 27 '17 at 17:19
• Indeed, I try with the package tikzpackagenodes and the following code : \node[text width=\textwidth] at (current page text area) {First line Second line. \lipsum}; but the text isn't fit to several pages... Moreover, it seems dangerous to alter the text flow by putting it inside a node because it can be very long text! – biblio Apr 27 '17 at 18:15
• Hmmm, paracol and tcolorbox? Worst case you can use a \vbox and \vsplit to break it into pages. – John Kormylo Apr 27 '17 at 18:52
• I'll try this kind of "hack" after having tried everything else ;-). – biblio Apr 27 '17 at 21:36

This uses tikzpagenodes, tikzmark and everypage. Don't forget to run it twice.

I used an environment mostly to make it hard to mess up. OTOH, I forgot to address nested environments.

\documentclass[a4paper,12pt]{book}
\usepackage{tikzpagenodes}
\usetikzlibrary{calc,tikzmark}
\usepackage{lipsum}
\usepackage{showframe}
\usepackage{everypage}

\makeatletter
\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

\newcounter{outlineid}
\newcounter{outlinedone}

\newenvironment{outline}{\par\tikzmark{begin\theoutlineid}\ignorespaces}%
{\par\tikzmark{end\theoutlineid}\stepcounter{outlineid}\ignorespaces}

\newcommand{\drawoutline}{\checkmarkpage{begin\theoutlinedone}{}%
{\begin{tikzpicture}[remember picture,overlay]
\path ({pic cs:begin\theoutlinedone}-| current page text area.west)
++(0pt,\ht\strutbox) coordinate(A);
\checkmarkpage{end\theoutlinedone}%
{\path (current page text area.south west) ++(0pt,-\dp\strutbox)
coordinate(B);}%
{\path ({pic cs:end\theoutlinedone}-| current page text area.west)
++(0pt,\ht\strutbox) coordinate(B);}%
{}% this should not happen
\fill[yellow] ($(A) + (-.333em,0pt)$) rectangle ($(B) + (-1cm,0pt)$);
\end{tikzpicture}}%
{\begin{tikzpicture}[remember picture,overlay]
\coordinate (A) at (current page text area.north west);
\checkmarkpage{end\theoutlinedone}%
{\path (current page text area.south west) ++(0pt,-\dp\strutbox)
coordinate(B);}%
{\path ({pic cs:end\theoutlinedone}-| current page text area.west)
++(0pt,\ht\strutbox) coordinate(B);}%
{}% this should not happen
\fill[yellow] ($(A) + (-.333em,0pt)$) rectangle ($(B) + (-1cm,0pt)$);
\end{tikzpicture}}%
\checkmarkpage{end\theoutlinedone}{}%
{\stepcounter{outlinedone}\drawoutline}%
{}% this should not happen
}

\begin{document}

\newpage

\thispagestyle{empty}

\lipsum[1]

Next line begins the rule :

\begin{outline}
\lipsum[2]
\end{outline}

Line above ends the rule.

Two on one page:
\begin{outline}
\lipsum[3]
\end{outline}

One on three pages:
\begin{outline}
\lipsum[4-12]
\end{outline}
That's all, folks.

\end{document}

• Yes, it works with a breakable boxes example I've just tried to process, thank you! I have now to study your code, and try to achieve my own attempt because it is the only way for me to understand Tex macros... – biblio Apr 28 '17 at 18:49
• Two questions, if you please: 1) Why is the newcommand \drawpicture not parametrizable with more than one argument? I can transform it in {\drawpicture}[1] but not "..."[2] or more...? 2) How can we transforme simply the two "\fill... rectangle" in order to draw something else, for instance to put symbols instead of just rules? – biblio Apr 28 '17 at 20:55
• No \drawpicture. \drawoutline is recursive (it calls itself) and intended for use in \AddEverypageHook, so no arguments. The key here is \checkmarkpage which determines which page the tikzmark is on. – John Kormylo Apr 29 '17 at 13:51
• You have the starting and stopping coordinates, (A) and (B). What exactly were you wanting to use? – John Kormylo Apr 29 '17 at 14:09
• Yes, drawoutline, sorry... In fact, there is another problem I encountered yesterday when trying to define two different environments with different names for environments and their variables and newcommands associated. It turns out that the rules are drawn even if there is no environment used for one of the two types of environments defined. This is hard to explain and I can't post the whole code here, so I think the best is to create a new question and close this one because finally, the "contract" is fulfilled as regard to what I asked first (I didn't mention the possibility for many envs). – biblio Apr 29 '17 at 14:17

This is a begining of answer. I can now draw the rule from an arbitrary line to another arbitrary line on the same page. Next step is to find a way for:

1) stopping the rule at the end of the page in front of the last line;

2) going to next page (something like current page+1 ??);

3) repeating 1)-2) till the end of the text...

And certainly one or two more things because the \zsavepos{lineend} of the code below doesn't take into account the fact that this position may be 1, 2, 3... x pages after the first! And how to know that?...

Important (to me...): I used a snippet of code (dimwithoutpt) from a portion of code named dimtomm (transform a dim in pt to mm), but I don't really understand the syntax of dimexpr (I read the etex-man, but... hmm!). If someone can explain me the way the code has to be read, it would be great :-).

Maybe there is a cleaner way to do the conversion and the setting of \beg and \portionheight, but I am not at all familiar with this kind of manipulation...

\documentclass[a4paper,12pt]{book}
\usepackage{tikz}
\usepackage{etoolbox}
\usepackage{lipsum}
\usepackage{showframe}
\usepackage{layout}
\usepackage{zref-savepos}

\makeatletter
\newcommand\dimwithoutpt[1]{%
\strip@pt\dimexpr 1\dimexpr#1\relax\relax%
}
\makeatother

\newlength\beg
\newlength\portionheight

\begin{document}
\layout{}

\newpage

\thispagestyle{empty}

\lipsum[1]

Next line begins the rule :

\zsavepos{linedeb}Begining of my new section.

\setlength{\beg}{dimwithoutpt{\paperheight-\zposy{linedeb}sp}pt}

\lipsum[2]\zsavepos{lineend}
\setlength{\portionheight}{\dimwithoutpt{\zposy{linedeb}sp-\zposy{lineend}sp}pt}

\begin{tikzpicture}[remember picture,overlay]
\node (back names) [shape=rectangle, fill=yellow, minimum height=\portionheight, minimum width=1cm, anchor=north west] at ([yshift=-\beg,xshift=1in+\oddsidemargin-1cm]current page.north west) {};
\end{tikzpicture}
Line above ends the rule.

And next :

\lipsum[3]

\end{document}

• Oh, just a line, not text. I would use the everypage package and send messages via the aux file.. – John Kormylo Apr 28 '17 at 14:25
• Whauouu! Seems much more complicated and opposite to what I am looking for, but thanks for the package that I didn't know... I made some progress: I can now store the page numbers of begining and ending text in counters pbeg and pend and I am going to try to implement the algorithm: IF page pend == pbeg, do what is coded above ELSE {draw line from begining of text to end of textheight; pbeg = pbeg-1; while pend > pbeg, do: draw line from begining of textheight to end of textheight; pbeg = pbeg-1; end while; draw line from begining of textheight to end of text}. – biblio Apr 28 '17 at 16:02