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?

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 '20 at 11:18
  • @PabloGonzálezL No idea of what it even is about.
    – egreg
    Apr 5 '20 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 '20 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 '20 at 12:45

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.