4

Following code shows the problem. I've declared a \newtcblisting with an optional argument.

\newtcblisting{codiltxb}[1][]{listing only, #1}

When the optional argument is present in further declarations, the listing is correct. (1st and 2nd boxes in figure)

\begin{codiltxb}[colback=green!20]
\Some code. Correct if the optional argument is present.
\end{codiltxb}

\begin{codiltxb}[]
\Some code. Correct if the optional argument, although empty, is present.
\end{codiltxb}

But if the optional argument is not present and the first word inside listing starts with \ (like \LaTeX commands), this first command disappears from resulting listing. (3rd box)

\begin{codiltxb}
\Some code. FAIL! No optional argument. First word (\LaTeX command) missing.
\end{codiltxb}

If the optional argument is not present and the first word doesn't start with \, the listing is correct again. (4th box)

\begin{codiltxb}
Some code. Correct! No optional argument. First word not \LaTeX command.
\end{codiltxb}

enter image description here

What's wrong with my code?

\documentclass{beamer}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{lmodern}
\usepackage[most]{tcolorbox}

\newtcblisting{codiltxb}[1][]{listing only, #1}

\begin{document}
\begin{frame}[fragile]
\frametitle{Listing}

\begin{codiltxb}[colback=green!20]
\Some code. Correct if the optional argument is present.
\end{codiltxb}

\begin{codiltxb}[]
\Some code. Correct if the optional argument, although empty, is present.
\end{codiltxb}

\begin{codiltxb}
\Some code. FAIL! No optional argument. First word (\LaTeX command) missing.
\end{codiltxb}

\begin{codiltxb}
Some code. Correct! No optional argument. First word not \LaTeX command.
\end{codiltxb}

\end{frame}

\end{document}

Note (2018-06-13): Although Thomas F. Sturm answer worked until now, some recent changes (2018-05-12) in xparse (see: xparse gobbles character(s) using an optional argument) make it fail again. A working solution while waiting for a better one is

\NewTCBListing{codiltxb}{ !O{} }{listing only, #1}
3
  • It seems that the first word is taken as the optional argument
    – MaxNoe
    May 29, 2015 at 15:33
  • @MaxNoe. No, in this case fourth example would also fail.
    – Ignasi
    May 29, 2015 at 15:46
  • Definitely a bug. The \Some token is not written out in the auxiliary file written by tcolorbox (with extension .listing). It seems to have to do with the grabbing of the optional argument.
    – egreg
    May 29, 2015 at 16:16

2 Answers 2

4

Update: !O{} instead of O{} inside \NewTCBListing{codiltxb}{ !O{} }{listing only, #1} to adapt to xparse changes with date of 2018-05-12.

Parsing problems with one optional argument only are known for \newtcblisting. The tcolorbox manual warns about it on page 245 (v2.60) and recommends to use \NewTCBListing instead.

The reason is the grabbing of the optional argument as egreg explained in his answer. It is done by the standard \@ifnextchar, if \newtcblisting is used. If \NewTCBListing is used, xparse code is used which is more suitable for the task.

So, replace

\newtcblisting{codiltxb}[1][]{listing only, #1}

by

\NewTCBListing{codiltxb}{ !O{} }{listing only, #1}

and you get the correct result.

enter image description here

\documentclass{beamer}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{lmodern}
\usepackage[most]{tcolorbox}

\NewTCBListing{codiltxb}{ !O{} }{listing only, #1}

\begin{document}
\begin{frame}[fragile]
\frametitle{Listing}

\begin{codiltxb}[colback=green!20]
\Some code. Correct if the optional argument is present.
\end{codiltxb}

\begin{codiltxb}[]
\Some code. Correct if the optional argument, although empty, is present.
\end{codiltxb}

\begin{codiltxb}
\Some code. FAIL! No optional argument. First word (\LaTeX command) missing.
\end{codiltxb}

\begin{codiltxb}
Some code. Correct! No optional argument. First word not \LaTeX command.
\end{codiltxb}

\end{frame}

\end{document}
3
  • But the use of the macro \NewTCBListing causes error --Undefined control sequence in the latest version of tcolorbox(5.0.2 2022-01-07). And its latest manuel still provide this macro on page 324 and 470.
    – lyl
    Mar 20, 2022 at 14:20
  • I mean, besides \tcbuselibrary{listings}, what else library needs to be loaded to use the macro \NewTCBListing
    – lyl
    Mar 20, 2022 at 15:02
  • @lyl An additional ! is needed before O for xparse 2018-05-12 and later. But, I do not get an Undefined control sequence error without it. Mar 28, 2022 at 8:11
2

This has to do with the grabbing of the optional argument; if I use \new@ifnextchar of amsmath and redefine \codiltxb the hard way, I get the expected result; this has the consequence that no space can intervene between the closing brace and the [, but should not be a big problem.

\documentclass{article}

\usepackage[T1]{fontenc} 
\usepackage[utf8]{inputenc}
\usepackage{lmodern}
\usepackage[most]{tcolorbox}
\usepackage{amsmath}

\newtcblisting{codiltxb}[1][]{listing only, #1}

\makeatletter
\renewcommand{\codiltxb}{%
  \new@ifnextchar[\@codiltxb{\tcblisting {listing only,options@for=codiltxb}}%
}
\def\@codiltxb[#1]{\tcblisting {listing only,#1,options@for=codiltxb}}
\makeatother


\begin{document}

\begin{codiltxb}[colback=green!20]
\Some code. Correct if the optional argument is present.
\end{codiltxb}

\begin{codiltxb}[]
\Some code. Correct if the optional argument, although empty, is present.
\end{codiltxb}

\begin{codiltxb}
\Some code. FAIL! No optional argument. First word (\LaTeX command) missing.
\end{codiltxb}

\begin{codiltxb}
Some code. Correct! No optional argument. First word not \LaTeX command.
\end{codiltxb}

\end{document}

enter image description here

0

You must log in to answer this question.

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