6

I had a very difficult time pinning this problem down, because it only exists when certain page-breaking conditions occur.

Problem

Text after environment mysteriously turns white under some conditions.

Hypothesis

When embedded listings code within a tcolorbox, it is possible that the scope is lost when a page break should occur that would split that environment, but instead of page breaking, LaTeX reaches a certain penalty such that LaTeX decides to keep the environment on one page.

I have no idea how to diagnose this issue.

Let me illustrate the problem.

Code with expected Output

This code works fine.

\documentclass{article}
\usepackage{fontspec}%compile with xelatex
\usepackage{listings}%for mylstcode
\usepackage{xparse}%for latex3 NewDocumentEnvironemnt
\usepackage[most]{tcolorbox}% for newtcolorbox and colorlet
\lstnewenvironment{mylstcode}[1][]{\lstset{#1,basicstyle=\ttfamily,columns=fullflexible,keepspaces=true,basewidth=0.5em,breaklines=true}}{} % for general code
\NewDocumentEnvironment{myexample}{ O{} O{} }
{
\colorlet{colexam}{blue!50!black} % The maximal total height of the upper and of the lower part of normal breakable tcolorboxes is about 65536pt (ca. 2300cm).
\newtcolorbox[]{myexamplebox}{%
    % Example Frame Start
    empty,% Empty previously set parameters
    title={Example: #1},% use \thetcbcounter to access the ithexample counter text
    % Attaching a box requires an overlay
  breakable=unlimited,
    attach boxed title to top left,
  % Ensures proper line breaking in longer titles
  minipage boxed title,
    % (boxed title style requires an overlay)
    boxed title style={empty,size=minimal,toprule=0pt,top=4pt,left=3mm,overlay={}},
    coltitle=colexam,fonttitle=\bfseries,
    before=\par\medskip\noindent,parbox=false,boxsep=0pt,left=3mm,right=0mm,top=2pt,breakable,pad at break=0mm,
    before upper=\csname @totalleftmargin\endcsname0pt, % Use instead of parbox=true. This ensures parskip is inherited by box.
    % Handles box when it exists on one page only
    overlay unbroken={\draw[colexam,line width=.5pt] ([xshift=-0pt]title.north west) -- ([xshift=-0pt]frame.south west); },
    % Handles multipage box: first page
    overlay first={\draw[colexam,line width=.5pt] ([xshift=-0pt]title.north west) -- ([xshift=-0pt]frame.south west); },
    % Handles multipage box: middle page
    overlay middle={\draw[colexam,line width=.5pt] ([xshift=-0pt]frame.north west) -- ([xshift=-0pt]frame.south west); },
    % Handles multipage box: last page
    overlay last={\draw[colexam,line width=.5pt] ([xshift=-0pt]frame.north west) -- ([xshift=-0pt]frame.south west); },%
  #2
    }
\begin{myexamplebox}}
{\end{myexamplebox}\endlist}
\begin{document}
\begingroup
\obeylines
1
1
1
1
\endgroup
%\vspace{-1ex} % Forcefully squeeze the two environments together
\begin{myexample}[for i in \{1..40\}; do echo \$i; done]
\begin{mylstcode}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
\end{mylstcode}
\end{myexample}
Here is a sentence that turns white.

Here is a sentence that turns white.

Here is a sentence that turns white.

Here is a sentence that turns white.
\end{document}

Output

enter image description here enter image description here

Code with unexpected output

Note that the only change is uncommenting \vspace{-1ex}

This typesets, but please examine the sentences below \end{myexample}. You should notice that the text below the page break becomes white!

\documentclass{article}
\usepackage{fontspec}%compile with xelatex
\usepackage{listings}%for mylstcode
\usepackage{xparse}%for latex3 NewDocumentEnvironemnt
\usepackage[most]{tcolorbox}% for newtcolorbox and colorlet
\lstnewenvironment{mylstcode}[1][]{\lstset{#1,basicstyle=\ttfamily,columns=fullflexible,keepspaces=true,basewidth=0.5em,breaklines=true}}{} % for general code
\NewDocumentEnvironment{myexample}{ O{} O{} }
{
\colorlet{colexam}{blue!50!black} % The maximal total height of the upper and of the lower part of normal breakable tcolorboxes is about 65536pt (ca. 2300cm).
\newtcolorbox[]{myexamplebox}{%
    % Example Frame Start
    empty,% Empty previously set parameters
    title={Example: #1},% use \thetcbcounter to access the ithexample counter text
    % Attaching a box requires an overlay
  breakable=unlimited,
    attach boxed title to top left,
  % Ensures proper line breaking in longer titles
  minipage boxed title,
    % (boxed title style requires an overlay)
    boxed title style={empty,size=minimal,toprule=0pt,top=4pt,left=3mm,overlay={}},
    coltitle=colexam,fonttitle=\bfseries,
    before=\par\medskip\noindent,parbox=false,boxsep=0pt,left=3mm,right=0mm,top=2pt,breakable,pad at break=0mm,
    before upper=\csname @totalleftmargin\endcsname0pt, % Use instead of parbox=true. This ensures parskip is inherited by box.
    % Handles box when it exists on one page only
    overlay unbroken={\draw[colexam,line width=.5pt] ([xshift=-0pt]title.north west) -- ([xshift=-0pt]frame.south west); },
    % Handles multipage box: first page
    overlay first={\draw[colexam,line width=.5pt] ([xshift=-0pt]title.north west) -- ([xshift=-0pt]frame.south west); },
    % Handles multipage box: middle page
    overlay middle={\draw[colexam,line width=.5pt] ([xshift=-0pt]frame.north west) -- ([xshift=-0pt]frame.south west); },
    % Handles multipage box: last page
    overlay last={\draw[colexam,line width=.5pt] ([xshift=-0pt]frame.north west) -- ([xshift=-0pt]frame.south west); },%
  #2
    }
\begin{myexamplebox}}
{\end{myexamplebox}\endlist}
\begin{document}
\begingroup
\obeylines
1
1
1
1
\endgroup
\vspace{-1ex} % Forcefully squeeze the two environments together
\begin{myexample}[for i in \{1..40\}; do echo \$i; done]
\begin{mylstcode}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
\end{mylstcode}
\end{myexample}
Here is a sentence that turns white.

Here is a sentence that turns white.

Here is a sentence that turns white.

Here is a sentence that turns white.
\end{document}

Note to Christian Hupfer: I know you do not like when I wrap tcolorbox with a \NewDocumentEnvironment :)

  • 1
    We'll see :-P:-P:-P -- do you mean the sentences are not visible any longer? – user31729 May 9 '16 at 12:56
  • 1
    note that { \colorlet{colexam}{blue!50!black} % puts two word spaces before the environment (which may, or may not be relevant but beware need for % at ends of lines!!) – David Carlisle May 9 '16 at 12:58
  • 2
    The text is only white if I use xelatex – user31729 May 9 '16 at 12:59
  • Using an external lstenvironment while tcolorbox provides the same functionality is 'weird', in my point of view – user31729 May 9 '16 at 13:06
  • I'll do a more robust testing later on, I am on my old notebook that is not really nice to work with. – user31729 May 9 '16 at 13:23
5

There's some strange interaction between listings wrapped in a tcolorbox and xelatex. I recommend to use a special \newtcblisting and use this (in the outer wrapper, if really needed ;-))

In this case the text does not vanish, regardless whether it is compiled with pdflatex, xelatex or lualatex.

\documentclass{article}
\usepackage{fontspec}%compile with xelatex
\usepackage{xparse}%for latex3 NewDocumentEnvironemnt
\usepackage[most]{tcolorbox}% for newtcolorbox and colorlet

\lstnewenvironment{mylstcode}[1][]{\lstset{#1,basicstyle=\ttfamily,columns=fullflexible,keepspaces=true,basewidth=0.5em,breaklines=true}}{} % for general code

\newtcblisting{myexamplelisting}[3][]{%
  listing only,
  listing options={#1,basicstyle=\ttfamily,columns=fullflexible,keepspaces=true,basewidth=0.5em,breaklines=true},
  empty,% Empty previously set parameters
  title={Example: #2},% use \thetcbcounter to access the ithexample counter text
  % Attaching a box requires an overlay
  breakable,%=unlimited,
  attach boxed title to top left,
  % Ensures proper line breaking in longer titles
    minipage boxed title,
    % (boxed title style requires an overlay)
    boxed title style={empty,size=minimal,toprule=0pt,top=4pt,left=3mm,overlay={}},
    coltitle=colexam,fonttitle=\bfseries,
    before=\par\medskip\noindent,parbox=false,boxsep=0pt,left=3mm,right=0mm,top=2pt,breakable,pad at break=0mm,
    before upper=\csname @totalleftmargin\endcsname0pt, % Use instead of parbox=true. This ensures parskip is inherited by box.
    % Handles box when it exists on one page only
    overlay unbroken={\draw[colexam,line width=.5pt] ([xshift=-0pt]title.north west) -- ([xshift=-0pt]frame.south west); },
    % Handles multipage box: first page
    overlay first={\draw[colexam,line width=.5pt] ([xshift=-0pt]title.north west) -- ([xshift=-0pt]frame.south west); },
    % Handles multipage box: middle page
    overlay middle={\draw[colexam,line width=.5pt] ([xshift=-0pt]frame.north west) -- ([xshift=-0pt]frame.south west); },
    % Handles multipage box: last page
    overlay last={\draw[colexam,line width=.5pt] ([xshift=-0pt]frame.north west) -- ([xshift=-0pt]frame.south west); },%
    #3%
}

\NewDocumentEnvironment{myexample}{ O{} O{} }
{%
  \colorlet{colexam}{blue!50!black} % The maximal total height of the upper and of the lower part of normal breakable tcolorboxes is about 65536pt (ca. 2300cm).
  \myexamplelisting{#1}{#2}%
}
{\endmyexamplelisting\endlist}
\begin{document}
\begingroup
\obeylines
1
1
1
1
\endgroup
\vspace{-1ex} % Forcefully squeeze the two environments together
\begin{myexample}[for i in \{1..40\}; do echo \$i; done]
\begin{mylstcode}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
\end{mylstcode}
\end{myexample}
Here is a sentence that turns white.

Here is a sentence that turns white.

Here is a sentence that turns white.

Here is a sentence that turns white.
\end{document}

enter image description here

  • I could not tell why the OPs code behaves odd using xelatex. Regarding to color management, pdflatex and xelatex produce sometimes different results. So, do it different is a not so bad answer ;-) – Thomas F. Sturm May 9 '16 at 15:26
  • @ThomasF.Sturm: Thanks. The original code works with lualatex however. A xelatex bug? – user31729 May 9 '16 at 15:32
  • @ChristianHupfer I am thankful for your help in offering an alternative. I must admit that I do not really like this option, because it restricts the contents of the example environment to code only. I often have a mixture of things. Losing that flexibility is a scary option, because it will affect many, many pages of documentation that I have already nicely written. :/ I wish we knew what the culprit was. If it is a xelatex bug, it would great to fix it! Would it be safe to add a \color{black} hook to the end of the tcolorbox / my wrapper as a cheap fix? – Jonathan Komar May 9 '16 at 19:06
  • @macmadness86: If it's a xelatex bug, it's beyond my knowledge to fix that. I must say, however, that your approach is actually not the best usage of capabilities. Mine is better (but not because it's by me), but since you have constructed your interface the other way round, I see that there's not much I can do from here. Try lualatex -- it works – user31729 May 9 '16 at 19:11
  • @ChristianHupfer It's difficult to say for me, if it is a xelatex bug. With xelatex, I stumble more often into color or other problems without knowing why, e.g. tex.stackexchange.com/questions/269426/…. But the reason could be that many packages are optimized for pdflatex (bug? incompatibility? feature?). – Thomas F. Sturm May 10 '16 at 7:36
2

Update 2016-09-16

Thomas F. Sturm mentions in the question comment that this problem may no longer exist, possibly due to a change in xelatex, but not due to a change in tcolorbox.


Solution until Compatibility Fix

In your Preamble add the following line to explicitly reset the font color to black after each tcolorbox:

  • \AfterEndEnvironment{myexample}{\color{black}}

Embedding tcolorbox within a list will negate the aforementioned fix outside of the list's scope. Therefore also add the following:

  • \AfterEndEnvironment{itemize}{\color{black}}
  • \AfterEndEnvironment{enumerate}{\color{black}}
  • \AfterEndEnvironment{description}{\color{black}}

Loading xcolor explicitly calls \color{black}.

Update 2016-05-12: Instead of explicitly setting "black", you could use \AtBeginDocument{\colorlet{defaultcolor}{.}} to make a defaultcolor colorlet that can be used after each myexample environment to restore the default color--at least until the packages/compiler work in harmony someday. See answers at xcolor - What is the equivalent of default text color?


Related Questions


mdframed Approach

Note this has a deal-breaker limitation

It has the disadvantage that the embedded listings environment does not properly break over pages.

Also, I've had about as much grief as I can handle with the listings package. It seems to frequently cause mysterious character issues.

\documentclass{article}
\usepackage{fontspec}% typeset with xelatex
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage[framemethod=tikz]{mdframed} % Add easy frames to paragraphs
\usepackage{xparse}
\usepackage{listings}

\lstnewenvironment{mylstcode}[1][]{\lstset{#1,basicstyle=\ttfamily,columns=fullflexible,keepspaces=true,basewidth=0.5em,breaklines=true}}{} % for general code

\mdfdefinestyle{exampledefault}{%
hidealllines=true,
linecolor=blue!20!black,
fontcolor=blue!20!black,
rightline=false,
leftline=true,
bottomline=false,
topline=false,
innerleftmargin=10pt,innerrightmargin=10,
frametitlerule=false,
frametitlerulecolor=blue!20!black,
frametitlebackgroundcolor=white,
frametitlerulewidth=1pt,
 firstextra={\path let \p1=(P), \p2=(O) in ($(\x2,0)+0.5*(0,\y1)$)
                           node[] {};},%
 secondextra={\path let \p1=(P), \p2=(O) in ($(\x2,0)+0.5*(0,\y1)$)
                           node[] {};},%
 middleextra={\path let \p1=(P), \p2=(O) in ($(\x2,0)+0.5*(0,\y1)$)
                           node[] {};},%
 singleextra={\path let \p1=(P), \p2=(O) in ($(\x2,0)+0.5*(0,\y1)$)
                           node[] {};},%
}
\NewDocumentEnvironment{myexample}{ O{} O{} }
{\begin{mdframed}[style=exampledefault,frametitle={Example: #1}]}
{\end{mdframed}}

\begin{document}
\begin{myexample}[for i in \{1..40\}; do echo \$i; done]
\begin{mylstcode}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
\end{mylstcode}
\end{myexample}
\end{document}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.