This question follows the one I asked here. I would like to override the following custom listings command from the tcolorbox
package and be able to have the following features implemented using xkeyval
:
- Define the language I want in the nested listings environment (with the option key
language=
), - Be able to choose if I need numbers or not (with the option key
withNumbers
) - Be able to choose if I need a caption or not (defined with the
title
option) - Specify a type which will put a translation before the title (if applicable). Among the available types:
codeSnippet
,code
,config
,prompt
.codeSnippet
andconfig
have numbers and title, the other two types haven't. And I should not be able to specify atitle
option if we are in aprompt
for example (or at least that option must do nothing and must not override thetype
).
The idea is to have the more generic command as possible and the final command must have all optional arguments with default value (especially for language, if it isn't specified I don't want a specific language formatting), for example:
\begin{code}[withNumbers, title=Hello world.cpp, type=codeSnippet, language=C++]
#include <iostream>
int main(int argc, char *argv[]) {
cout << "hello world" << endl;
}
\end{document}
In the afternoon, I also tried to have xkeyval boolkey
in a way to achieve what I wanted to show in the example above.
If the key is present the value is true, if absent, the value is false. In this example, if I specify withNumbers
, I want numbers. If it isn't specified, numbers should be absent of the final rendered listing environment.
The left
statement from the newtcblisting
caption must be removed if no numbers are present, in order to avoid an unneeded shift at the left of the listings environment.
By default, no language and no numbers. The modifications made to the following snippet of code does not have to break the feature brought in the aforementioned question, nor does it have to use a package other than tcolorbox
as I might customize the box
level a bit further in the future.
I tried the whole afternoon studying the xkeyval
package and customizing the following command by enclosing it in a \renewcommand
environment, but haven't succeeded at all :-(
The minimum working example with the \newtcblisting
command I talked about:
\documentclass[oneside]{report}
\usepackage{fontspec}
\setmonofont{Bitstream Vera Sans Mono}[Scale=MatchLowercase]
\usepackage[margin=2.5cm]{geometry}
\usepackage{listings}
\usepackage{tcolorbox}
\tcbuselibrary{breakable}
\tcbuselibrary{skins}
\tcbuselibrary{listings}
\usepackage{caption}
\usepackage{translations}
\DeclareTranslationFallback{codeSnippet}
{Code snippet}
\DeclareTranslation{English}{codeSnippet}
{Code snippet}
\DeclareTranslation{Dutch}{codeSnippet}
{Codefragment}
\DeclareTranslation{French}{codeSnippet}
{Extrait de code}
\usepackage[main=french, german]{babel}
% Let's create style to inherit from in other custom environments based on listings. Indeed, we do not want copy paste always the same customization for each environments.
\lstdefinestyle{custom}{
% NoAutoSpacing prevents a space before colons to be added when the french
% language is loaded with babel.
% src.: https://tex.stackexchange.com/a/117767/66964
% https://tex.stackexchange.com/a/200215/66964
basicstyle=\linespread{1}\normalsize\ttfamily\NoAutoSpacing,
% Space separated words are not properly aligned on next lines if `columns` statement is set to
% flexible. Default is 'fixed'.
columns=fixed,
breaklines=true,
breakautoindent=false,
breakindent=0pt,
% Sets default tabsize to 4 spaces
tabsize=4,
% Normally used to define delimiters in code listings like begin and end
% keywords, but it has a side effect allowing linebreaks. We are thus gonna
% use that ugly trick to force lstinline statements to break the line at
% the underscore character if there is not enough room for the string. This
% is an ugly hack because it has a side effect: the _ character becomes
% a suitable breakpoint for both sides. This can create either foo_\n bar
% or foo\n _bar, but this cannot be avoided.
%moredelim=[s]{_}{_},
% Put in bold words surrounded by @@
% [is] specifies the style.
% i: standing for "invisible", ask for the delimiters @@ to invisible in the rendered version
% s: standing for "string", ask for two delimiters, one starting the expression and the other closing the expression.
moredelim={[is][keywordstyle]{@@}{@@}}
}
% Code environment. Does inherit from lstset settings thanks to style.
\newtcblisting[auto counter]{code}[2][]{%
listing only,
breakable,
top=0.5pt,
bottom=0.5pt,
left=6mm,
sharp corners,
boxrule=0pt,
bottomrule=1pt,
toprule=1pt,
enhanced jigsaw,
listing options={
style=custom,
numbers=left,
numberstyle=\tiny,
},
lefttitle=0pt,
coltitle=black,
colbacktitle=white,
% Crashes on long lstlisting lines. \the\baselineskip reports 12.0pt. 1.2 * 12.0 = 14.4
%borderline north={1pt}{1.2\baselineskip}{dashed},
borderline north={1pt}{14.4pt}{dashed},
title={\GetTranslation{codeSnippet} \thetcbcounter: #2},#1
}
\begin{document}
\begin{code}{Some great title}
one
two
three
four
\end{code}
\end{document}
Thanks you in advance for your help.
EDIT: I'm now switching my own class file to pgfkeys (cf. my new question). So your solution can use pgfkeys instead of xkeyval.
(x)keyval
(used bylistings
) andpgfkeys
(used bytcolorbox
) are not compatible.tcolorbox
usedpgfkeys
: the documentation has only mentions ofpgf
. Indeed this can be a problem and have incompatibilities withxkeyval
. Waiting on your ideas, I'm stuck here.xkevyal
andpgfkeys
:-(