3

I would like to use tcolorbox listing environments to format listings in an interesting way. For each listing, I would like to have an title in a way, that in default it would be like Listing (number), but if specified (as optional argument) it would be the specified text. This text should be also used in underlay as a decoration.

In next MWE, first environment clisting works, but has no parametrization and mainly shows, what I am trying to achieve.

Second environment cxparselisting shows how I thought it should be achieved. /tcb/xparse library command \NewTCBListing is used and O{text} is used for text to be used for #1, but it doesnt work and in stated cxparselisting content first letter # is interpreted as optional argument (as described here: Problem with tcblisting: First listed LaTeX command is missing ).

I must have misunderstood, how to create optiOnal arguments in xparse.

Third environment, xmllisting shows also what I want to achieve, and surprisingly works with non-xparse syntax (eventhough first ?token tab is absorbed).

How can I construct (preferably) \NewTCBListing to have one optional argument with default value (that is parametrized, so can be used in multiple tcbox options)?

MWE: (delete % near comment environments to disable not-working cxparselisting and be able to compile MWE)

\documentclass [a4paper, 11pt, twoside, openright] {scrbook}

\usepackage{comment}

\usepackage[dvipsnames,x11names,svgnames,table]{xcolor}

\usepackage{enumitem}

\usepackage[skins, vignette, breakable, hooks, xparse, minted, raster]{tcolorbox}
\tcbset{listing engine=minted}

\newcounter{ccounter}

\newtcblisting[use counter=ccounter]{clisting}{% Works, but without parametrization
    colframe=green!75!black,%
    listing only,%
%   title=#1,
    title=C listing \theccounter,
    minted language=C,
    underlay middle and last={%
    \ifnumequal{\numexpr\tcbsegmentstate}{2}{\begin{tcbclipinterior}\fill[red!10!blue!10!white] ([xshift=-7mm]frame.south east)
      rectangle (frame.north east) node [anchor=south east,rotate=90] {\bfseries \textcolor{black}{C listing \theccounter -- Output}};\end{tcbclipinterior}%
    }
    {\begin{tcbclipinterior}\fill[red!10!blue!10!white] ([xshift=-7mm]frame.south east)
      rectangle (frame.north east) node [anchor=south east,rotate=90] {\bfseries \textcolor{black}{C listing \theccounter}};\end{tcbclipinterior}%
    }
    },% 
}

%\begin{comment}
\NewTCBListing[use counter=ccounter]{cxparselisting}{ O{C~listing~\theccounter} }{% Doesnt work, probably still grabs first letter in optional argument scan
    colframe=green!75!black,%
    listing only,%
    title=#1,
    minted language=C,
    underlay middle and last={%
    \ifnumequal{\numexpr\tcbsegmentstate}{2}{\begin{tcbclipinterior}\fill[red!10!blue!10!white] ([xshift=-7mm]frame.south east)
      rectangle (frame.north east) node [anchor=south east,rotate=90] {\bfseries \textcolor{black}{#1 -- Output}};\end{tcbclipinterior}%
    }
    {\begin{tcbclipinterior}\fill[red!10!blue!10!white] ([xshift=-7mm]frame.south east)
      rectangle (frame.north east) node [anchor=south east,rotate=90] {\bfseries \textcolor{black}{#1}};\end{tcbclipinterior}%
    }
    },% 
}
%\end{comment}

\newcounter{xmlcounter}

\newtcblisting[use counter=xmlcounter]{xmllisting}[1][XML listing \thexmlcounter]{% Surprisingly, works ...
    colframe=blue!75!black,%
    listing only,%
    title=#1,
    minted language=XML,
    underlay middle and last={%
    \ifnumequal{\numexpr\tcbsegmentstate}{2}{\begin{tcbclipinterior}\fill[red!10!blue!10!white] ([xshift=-7mm]frame.south east)
      rectangle (frame.north east) node [anchor=south east,rotate=90] {\bfseries \textcolor{black}{#1 -- Output}};\end{tcbclipinterior}%
    }
    {\begin{tcbclipinterior}\fill[red!10!blue!10!white] ([xshift=-7mm]frame.south east)
      rectangle (frame.north east) node [anchor=south east,rotate=90] {\bfseries \textcolor{black}{#1}};\end{tcbclipinterior}%
    }
    },% 
}

\begin{document}
\begin{clisting}
#include <stdio.h>

int main() {
  printf(''Hello World!\n'');
  return 0;
}
\end{clisting}

\bigskip

%\begin{comment}
\begin{cxparselisting}
#include <stdio.h>

int main() {
  printf(''Hello World!\n'');
  return 0;
}
\end{cxparselisting}
%\end{comment}

\bigskip

\begin{xmllisting}
    <message>
    <text>Hello, world!</text>
    </message>
\end{xmllisting}

\end{document}

1 Answer 1

4

On page 453 of the tcolorbox documentation the problem is explained:

With date of 2018-05-12, the xparse [13] package changed the argument collection process. Now, spaces are ignored which leads to a serious change for listing environments ending with an optional argument like O{}. The former behaviour of respecting spaces can be preserved by adding a «!».

xparse was adapted later to reduce the occurrences of that problem, but for tcblisting the statement of the documentation is still true (unfortunately).

So, you have to replace

\NewTCBListing[use counter=ccounter]{cxparselisting}{ O{C~listing~\theccounter} }{% 

by

\NewTCBListing[use counter=ccounter]{cxparselisting}{ !O{C~listing~\theccounter} }{% 

to solve (circumvent) the problem.

You must log in to answer this question.

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