0

This question is very similar to DeclareTCBListing and write percent a file(thanks Schrödinger's cat) but the approach is different, I think I have an idea of what is going on:

The tcolorbox package gives a special treatment to the % character when it is going to be written to a file, this example works OK:

\documentclass[10pt]{article}
\usepackage{tcolorbox}
\tcbuselibrary{listings,breakable,skins,xparse}
\DeclareTCBListing{mytcblisting}{ O{} }
  {%
     bottom=-1mm, boxrule=0.4pt, boxsep=0mm, top=-1mm, arc=0mm,%
     title style={draw=none,fill=none},
      enhanced, autoparskip, 
    freelance,#1%
  }
\begin{document}
% OK, from doc pag 130
\def\percent{\%}
\begin{tcblisting}{title=Normal}
%\begin{center}\bfseries
This is my 5\percent\ text
and this is my 10\% text.
%\end{center}
\end{tcblisting}

% No rror

\begin{mytcblisting}
%\begin{center}\bfseries
This is my 5\percent\ text
and this is my 10\% text.
%\end{center}
\end{mytcblisting}

\end{document}

But, by passing the code inside \ExplSyntaxOn and \ExplSyntaxOff this special treatment is lost, This example fails:

MWE

\documentclass[10pt]{article}
\usepackage{tcolorbox}
\tcbuselibrary{listings,breakable,skins,xparse}
\def\percent{\%}
% Colors
\definecolor{colKeys}{rgb}{0,0,1}
\definecolor{colIdentifier}{rgb}{0,0,0}
\definecolor{colComments}{rgb}{1,0,0}
\definecolor{colString}{rgb}{0,0.5,0}
% Listings
\lstdefinestyle{example}{
  basicstyle=\ttfamily\small, %
  identifierstyle=\color{colIdentifier}, %
  keywordstyle=\color{colKeys}, %
  stringstyle=\color{colString}, %
  commentstyle=\color{colComments}, %
  numbersep=3pt,%
  numberstyle=\tiny\color{red}%
}
\ExplSyntaxOn
\bool_new:N \l_example_margin_left_bool
\tl_new:N \l_example_position_tl
\tl_new:N \l_example_haling_tl
\keys_define:nn { examplekeys }
  {
    codefile .code:n = \tl_set:Nn \l_example_codefile_tl {#1},
    lstconf  .code:n = \tl_set:Nn \l_example_lstconf_tl {#1},
    fcolor   .code:n = \tl_set:Nn \l_example_fcolor_tl {#1},
    bcolor   .code:n = \tl_set:Nn \l_example_bcolor_tl {#1},
    hsep     .code:n = \tl_set:Nn \l_example_hsep_tl {#1},
    vsep     .code:n = \tl_set:Nn \l_example_vsep_tl {#1},
    width    .code:n = \tl_set:Nn \l_example_width_tl {#1},
    align    .choice:  ,
    align/j  .code:n = \tl_set:Nn \l_example_haling_tl { justify },
    align/l  .code:n = \tl_set:Nn \l_example_haling_tl { flush~left } ,
    align/r  .code:n = \tl_set:Nn \l_example_haling_tl { flush~right } ,
    align/c  .code:n = \tl_set:Nn \l_example_haling_tl { flush~center } ,
    pos      .choice:  ,
    pos/r    .code:n = {
                         \bool_set_true:N \l_example_margin_left_bool
                         \tl_set:Nn \l_example_position_tl { listing~outside~text }
                       },
    pos/l    .code:n = {
                         \bool_set_false:N \l_example_margin_left_bool
                         \tl_set:Nn \l_example_position_tl { text~outside~listing }
                       },
    pos/t    .code:n = \tl_set:Nn \l_example_position_tl { listing~above~text } ,
    pos/b    .code:n = \tl_set:Nn \l_example_position_tl { text~above~listing } ,
  }

\keys_set:nn { examplekeys }
  {
    codefile = \jobname-tmp.ltx,
    lstconf  = { style=example,numbers=left },
    fcolor   = red!75!black,
    bcolor   = red!5!white,
    hsep     = 5mm,
    vsep     = 5mm,
    width    = 0.5\linewidth,
    pos      = l,
    align    = j,
  }
\DeclareTCBListing{mytcblisting}{ O{} }
  {%
    bottom=-1mm, boxrule=0.4pt, boxsep=0mm, top=-1mm, arc=0mm,%
    title~style={draw=none,fill=none}, enhanced, autoparskip, freelance,%
    %listing~options={ \tl_use:N \l_example_lstconf_tl },%
    listing~options = {style=example,numbers=left},
    listing~file    = \tl_use:N \l_example_codefile_tl,
    sidebyside~gap  = \tl_use:N \l_example_hsep_tl,
    middle          = \tl_use:N \l_example_vsep_tl,
    halign~lower    = \tl_use:N \l_example_haling_tl,
    colframe        = \tl_use:N \l_example_fcolor_tl,
    colback         = \tl_use:N \l_example_bcolor_tl,
    \tl_use:N \l_example_position_tl,
  }
\NewDocumentEnvironment{ example }{ O{} }
  {
    \group_begin:
    \IfNoValueF{#1}{ \keys_set:nn { examplekeys } { #1 } }
    \bool_if:NTF { \l_example_margin_left_bool }
      { \tcbset{ righthand~width = \tl_use:N \l_example_width_tl } }
      { \tcbset{ lefthand~width  = \tl_use:N \l_example_width_tl }  }
    \mytcblisting
  }
  {
    \endmytcblisting
    \group_end:
  }

\ExplSyntaxOff
\begin{document}

\begin{tcblisting}{title=Normal}
%\begin{center}\bfseries
This is my 5\percent\ text
and this is my 10\% text.
%\end{center}
\end{tcblisting}

\begin{example}[fcolor=blue,width=3cm, pos=t, vsep=2mm, align=j]
%\begin{center}\bfseries
This is my 5\percent\ text
and this is my 10\% text.
%\end{center}
\end{example}

% no [opt]
\begin{example}
Some
text
in
some
lines
\end{example}

\begin{example}[pos=r,width = 3cm]
This is my
\LaTeX\ box.
\end{example}

\end{document}

How do I define % to be treated in the right way?

1 Answer 1

2

You're defining mytcblisting to look for an optional argument, which obviously doesn't exist, because the optional argument has already been consumed by example. Looking for it causes the initial % to be tokenized prematurely.

\NewTCBListing{mytcblisting}{ }
  {
    bottom=-1mm, boxrule=0.4pt, boxsep=0mm, top=-1mm, arc=0mm,
    title~style={draw=none,fill=none}, enhanced, autoparskip, freelance,
    %listing~options={ \tl_use:N \l_example_lstconf_tl },
    listing~options = {style=example,numbers=left},
    listing~file    = \tl_use:N \l_example_codefile_tl,
    sidebyside~gap  = \tl_use:N \l_example_hsep_tl,
    middle          = \tl_use:N \l_example_vsep_tl,
    halign~lower    = \tl_use:N \l_example_haling_tl,
    colframe        = \tl_use:N \l_example_fcolor_tl,
    colback         = \tl_use:N \l_example_bcolor_tl,
    \tl_use:N \l_example_position_tl,
  }

You should also do

\NewDocumentEnvironment{ example }{ !O{} }
  {
    \IfNoValueF{#1}{ \keys_set:nn { examplekeys } { #1 } }
    \bool_if:NTF { \l_example_margin_left_bool }
      { \tcbset{ righthand~width = \tl_use:N \l_example_width_tl } }
      { \tcbset{ lefthand~width  = \tl_use:N \l_example_width_tl }  }
    \mytcblisting
  }
  {
    \endmytcblisting
  }

so the [ has to be next to \begin{example} and a missing optional argument will not cause the tokenization of the initial %.

I removed the useless \group_begin: and the matching \group_end: (environments provide them automatically).

4
  • You are the man, I couldn't catch the problem with the blessed %... to avoid asking a new question (related to the same thing), you can tell me why the lstconf key doesn't work? Apr 5, 2020 at 11:18
  • @PabloGonzálezL No idea of what it even is about.
    – egreg
    Apr 5, 2020 at 12:34
  • I have expressed myself badly (sorry for this), I had to define that key lstconf because I could not adapt your trick to pass unknown keys (tex.stackexchange.com/a/98392/7832) directly to tcolorbox ... so I'll have to define a key for each option you want to use :( anyway I've already made it work :), Maybe I should ask another question with this? Apr 5, 2020 at 12:43
  • Of course the key works only halfway, I can't get through using , and I had to add a Boolean variable ...it got ugly Apr 5, 2020 at 12:45

You must log in to answer this question.

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