4

Problem Statement

I'd like to conditionally add a TikZ overlay at the start of some paragraphs or figures.

Failed attempt to draw red boxes around the first letter of each paragraph

In this example (see code below), I'd like to conditionally insert red boxes around the first character of "Paragraph 3" and "External file". However, because the external file contains empty lines, TeX sets my overlay picture in a separate paragraph on its own. One may argue that I should simply put the \RedBox command into figure1.tex, just in font of the actual content. However, let's assume for the sake of argument that the included files are provided externally and can not easily be modified.

The problem is that the red box is not around the first character, because the \tikz command starts a new paragraph. I think this is because it forces TeX to enter horizontal mode or something. More details can be found in the question Tikzpicture with overlay takes up space.

\documentclass{article}
\usepackage{tikz}
\usepackage{lipsum}

\def\RedBox{\tikz[overlay, remember picture] \draw[red] (0,0) rectangle (0.6em, 1em);}

\begin{filecontents}{figure1.tex}
% Some random definitions which may or may not contain whitespace or newlines
\def\MyHelperMacro{foo}

External file which may or may not contain empty lines. \MyHelperMacro
\end{filecontents}


\begin{document}

Paragraph 1 bla bla

Paragraph 2 bla bla

% Here the overlay works as expected
\RedBox
Paraghraph 3 bla bla.

% Here the overlay starts a new paragraph, which is undesired!
\RedBox
\input{figure1.tex}

Paragraph 5
\end{document}

Not a Solution

The question Tikzpicture with overlay takes up space explains why this is the case and why it can't be fixed easily (allegedly because the \tikz command creates a 'whatsit', whatever that may be). It is suggested to use \nointerlineskip, but that doesn't solve the problem, neither in the \RedBox command (as shown below) nor in the included file (which is sometimes infeasible; output is still wrong, but not shown here).

\def\RedBox{\nointerlineskip\tikz[overlay, remember picture] \draw[red] (0,0) rectangle (0.6em, 1em);}

Using \nointerlineskip doesn't fix the problem

Partial Solution?

So I thought, it it were possible to store the \tikz command somewhere and emit it only when a new paragraph is started by some other following content, then it wouldn't start a new a paragraph on its own. As it turns out, there is \everypar{stuff} which prepends stuff to all following paragraphs. So the following achieves the desired effect, but still has some problems.

\def\RedBox{%
    \everypar{%
        \tikz[overlay, remember picture] \draw[red] (0,0) rectangle (0.6em, 1em);%
        \everypar{}%
    }%
}

Working but inflexible solution

For example, if you added a second command \GreenCircle which uses the same mechanism, you can't have both a \RedBox and a \GreenCircle on the same paragraph because the second one erases the \everypar that was set by the first command. And if you had another package which sets \everypar, then it gets messed up the first time you use one of the overlay commands.

So finally, after a lot of setup and explanation, we get to the actual question:

Is there a better way to inject content at the start of the next paragraph, which doesn't mess up other usages of \everypar?

1 Answer 1

2

How about really inserting a picture at the beginning of every paragraph but just change its contents with the macros like \RedBox, \GreenCircle and so on?

\documentclass{article}
\usepackage{tikz}
\usepackage{lipsum}

\begin{filecontents}{figure1.tex}
% Some random definitions which may or may not contain whitespace or newlines
\def\MyHelperMacro{foo}

External file which may or may not contain empty lines. \MyHelperMacro
\end{filecontents}

\newcommand{\ResetPar}{\tikzset{every par/.code={}}}
\newcommand\RedBox{\tikzset{every par/.append code={\draw[red] (0,0) rectangle (0.6em,
1em);}}}
\newcommand\GreenCircle{\tikzset{every par/.append code={\draw[green!70!black] (0.3em,0.4em)
 circle[x radius=0.3em,y radius=0.4em];}}}

\ResetPar
\begin{document}
\everypar{%
        \tikz[overlay, remember picture]{
        \tikzset{every par}
%       \draw[red] (0,0) rectangle (0.6em, 1em);%
        }%
    }%


Paragraph 1 bla bla

Paragraph 2 bla bla

% Here the overlay works as expected
\RedBox
Paraghraph 3 bla bla.

% Here the overlay starts a new paragraph, which is undesired!
%\RedBox
\input{figure1.tex}
\ResetPar

Paragraph 5

\GreenCircle
Paraghraph 6 bla bla.

% Here the overlay starts a new paragraph, which is undesired!
%\RedBox
\input{figure1.tex}
\ResetPar

Paragraph 7

\RedBox\GreenCircle
Paraghraph 8 bla bla.

% Here the overlay starts a new paragraph, which is undesired!
%\RedBox
\input{figure1.tex}
\ResetPar

\end{document}

enter image description here

1
  • Good idea. You could probable make it a little more flexible by using a token list instead of a tikzpicture with .append code, thus allowing any TeX code to be added at the start of the next paragraph. But it would still break if someone else or some package uses \everypar for a different purpose. Also, I'd put \ResetPar into the \everypar code, because In my case it shouldn't repeat by default.
    – Fritz
    Commented Sep 23, 2019 at 7:46

You must log in to answer this question.

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