2

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}
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.

| improve this answer | |

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.