T-F-S / tcolorbox

A LaTeX package to create highly customizable colored boxes.
http://www.ctan.org/pkg/tcolorbox
LaTeX Project Public License v1.3c
228 stars 16 forks source link

broken listing decreases interline space #298

Open mbertucci47 opened 2 days ago

mbertucci47 commented 2 days ago

If a tcb listing breaks at the right place, it can decrease the space between text in the code. I encountered this in the documentation of my package, which hopefully explains the setup. I tried for an hour to replicate the issue with a more minimal setup but I could not, so either the issue is specific to my using \tcbusetemplisting or I'm missing something. Here's an example.

\documentclass{article}

\usepackage{tcolorbox}
\tcbuselibrary{minted,breakable}
\usepackage{kantlipsum}

\tcbset{
  listing engine=minted,
  minted language=latex,
  withpreamble/.style = {
    before upper = {%
      {\ttfamily\itshape \% preamble}%
      \vspace{-8pt}%
      \tcbusetemplisting
      \noindent{\ttfamily\itshape \% document}%
      \vspace{-8pt}%
      }
    }
  }

\NewTCBListing{codeex}{ O{} }
  {
    boxrule=0pt,
    breakable,
    #1
  }

\begin{document}

\begin{tcbwritetemp}
Some preamble code
\end{tcbwritetemp}

\begin{codeex}[withpreamble]
Some code to print
\end{codeex}

\kant[1-2]
\kant[3][1-5]

\begin{tcbwritetemp}
Some preamble code
\end{tcbwritetemp}

\begin{codeex}[withpreamble]
Some code to print
\end{codeex}

\end{document}

lll-1

As you can see the space between % preamble and % document and the proceeding text is decreased significantly for the broken box.

muzimuzhi commented 2 days ago

\tcbusetemplisting is the culprit.

When /tcb/listing engine=minted, \tcbusetemplisting will call an \inputminted, whose output is wrapped in a \list, thus typical upper and lower list skips consisting of \topsep, \parskip, and optionally \partopsep are inserted.

As \topsep has a shrinking part, when it shrinks you get inconsistent interline spacings.

One workaround is to locally change \topsep for \tcbusetemplisting:

% \vspace{-8pt}%
{\setminted{listparameters={\topsep=0pt}}\tcbusetemplisting}
Full example

```tex \documentclass{article} \usepackage{tcolorbox} \tcbuselibrary{minted,breakable} \usepackage{kantlipsum} \tcbset{ listing engine=minted, minted language=latex, withpreamble/.style = { before upper = {% {\ttfamily\itshape \% preamble}% % \vspace{-8pt}% {\setminted{listparameters={\topsep=0pt}}\tcbusetemplisting} \noindent{\ttfamily\itshape \% document}% \vspace{-8pt}% } } } \NewTCBListing{codeex}{ O{} } { boxrule=0pt, breakable, #1 } \begin{document} \begin{tcbwritetemp} Some preamble code \end{tcbwritetemp} \begin{codeex}[withpreamble] Some code to print \end{codeex} \kant[1-2] \kant[3][1-5] \begin{tcbwritetemp} Some preamble code \end{tcbwritetemp} \begin{codeex}[withpreamble] Some code to print \end{codeex} \end{document} ```

Header Header
image image

BTW in the original example, changing \kant[3][1-5] to \kant[3][1-4] (or simply adding \enlargethispage{\baselineskip}) and the interline spacing will be much consistent. This suggests that it's related to shrinkable part(s) of skip(s).

muzimuzhi commented 1 day ago

I can't help but feel % preamble and % document lines should be highlighted in LaTeX too.

Below is an attempt which highlights then typesets all four components (preamble comment, preamble code, document comment, document code) one by one. The best solution is to highlight all the four components in one run, which needs hack into tcblisting env.

Highlight % preamble and % document too

```tex \documentclass{article} \usepackage{tcolorbox} \tcbuselibrary{minted,breakable} \usepackage{kantlipsum} \makeatletter \newbox\doc@preamble \newbox\doc@document \begin{tcbwritetemp} % preamble \end{tcbwritetemp} \setbox\doc@preamble=\hbox{\setminted{envname=VerbEnv}\tcbusetemplisting} \begin{tcbwritetemp} % document \end{tcbwritetemp} \setbox\doc@document=\hbox{\setminted{envname=VerbEnv}\tcbusetemplisting} \tcbset{ listing engine=minted, minted language=latex, withpreamble/.style = { before upper = {% % affects \tcbsettemplisting and the original upper \setminted{listparameters={\topsep=0pt \partopsep=0pt}}% \usebox\doc@preamble\par \tcbusetemplisting \usebox\doc@document\par } } } \makeatother \NewTCBListing{codeex}{ O{} } { boxrule=0pt, breakable, #1 } \begin{document} \begin{tcbwritetemp} Some preamble code \end{tcbwritetemp} \begin{codeex}[withpreamble] Some code to print \end{codeex} \kant[1-2] \kant[3][1-5] \begin{tcbwritetemp} Some preamble code \end{tcbwritetemp} \begin{codeex}[withpreamble] Some code to print \end{codeex} \end{document} ```

Header Header
image image
muzimuzhi commented 1 day ago

I can't help but feel % preamble and % document lines should be highlighted in LaTeX too.

A revised version which automatically prepends % preamble or % document to the temp file, depending on which part is being recorded, by making use of existing hook \tcb@verbatim@begin@hook. Note the current approach is not compatible with {tcbexternal} env from the external library.

Key parts

% extension to tcolorbox
\tcbset{
  before verbatim write app/.code={%
    \appto\tcb@verbatim@begin@hook{\tcb@iow@write{#1}}},
  % provided for symmetry, but not used
  after verbatim write pre/.code={%
    \preto\tcb@verbatim@end@hook{\tcb@iow@write{#1}}},
}

% user config
\tcbset{
  mark preamble/.style={
    before verbatim write app={\@percentchar\space preamble},
  },
  mark document/.style={
    before verbatim write app={\@percentchar\space document},
  },
}
Full example: Highlight % preamble and % document too, v2

```tex \documentclass{article} \usepackage{tcolorbox} \tcbuselibrary{minted,breakable} \usepackage{kantlipsum} \makeatletter % extension to tcolorbox \tcbset{ before verbatim write app/.code={% \appto\tcb@verbatim@begin@hook{\tcb@iow@write{#1}}}, % provided for symmetry, but not used after verbatim write pre/.code={% \preto\tcb@verbatim@end@hook{\tcb@iow@write{#1}}}, } % user config \tcbset{ mark preamble/.style={ before verbatim write app={\@percentchar\space preamble}, }, mark document/.style={ before verbatim write app={\@percentchar\space document}, }, } \tcbset{ listing engine=minted, minted language=latex, withpreamble/.style = { mark document, before upper = {% % affects both the \tcbsettemplisting and the original upper \setminted{listparameters={\topsep=0pt \partopsep=0pt}}% \tcbusetemplisting } } } \makeatother \NewTCBListing{codeex}{ O{} } { boxrule=0pt, breakable, #1 } % a custom {tcbwritetemp} env to execute custom tcb options \NewDocumentEnvironment{codepreamble}{}{% \tcbset{mark preamble}% \tcbwritetemp }{% \endtcbwritetemp } \begin{document} \begin{codepreamble} Some preamble code \end{codepreamble} \begin{codeex}[withpreamble] Some code to print \end{codeex} \kant[1-2] \kant[3][1-5] \begin{codepreamble} Some preamble code 2 \end{codepreamble} \begin{codeex}[withpreamble] Some code to print 2 \end{codeex} \end{document} ```

The output should be visually unchanged.

mbertucci47 commented 1 day ago

@muzimuzhi As always, thanks for your in-depth investigation. So I guess this is not a bug, just how minted does things, right?