2

I want to define a new environment whose implementation depends on another environment. The first environment should accept a list of key-value options. Some of these options are for use only on this first environment. All options not known to the first environment are to be passed to the other environment.

Is there any package for dealing with options filtering in LaTeX?

5
  • 1
    You've tagged pgfkeys but the question is open for all keyval packages: should we prefer pgfkeys?
    – Joseph Wright
    Jul 25, 2014 at 19:47
  • Are these environments used in a nested sense, or completely separate, or perhaps both?
    – Werner
    Jul 25, 2014 at 20:56
  • pgfkeys has /.try handler.
    – percusse
    Jul 25, 2014 at 20:57
  • @JosephWright I have started programming this environment using pfgkeys, as it seems to be very powerful, but if other keyval package offers some useful feature to accomplish what I need, than I can try it.
    – Romildo
    Jul 25, 2014 at 23:34
  • @Werner, I think I can say the environments will be nested. The environment will be used to typeset code listings. The contents of the environment will be typeset with the help of pygments, which will use some macros to add style to the listing. The result will be the content of another environment like mdframed, tcolorbox, boite, framed, Verbatim, which would allow drawing a frame around the listing, setting the background, or producing other effects.
    – Romildo
    Jul 25, 2014 at 23:42

1 Answer 1

1

There are different key=value packages for which you can do the following (in essence, every key=value package that allows you to define unknown-handlers yourself). I'll show an example using expkv of this approach (disclaimer: I'm expkv's author).

\documentclass{article}

\usepackage{tcolorbox}
\usepackage{expkv-def}

\ekvdefinekeys{myenv}
  {
     store blubb = \myenvBlubb
    ,store foo   = \myenvFoo
    ,store bar   = \myenvBar
    % this implements the filtering, instead of throwing errors for unknown keys
    % we store them in a list
    ,protected unknown noval =
      \edef\myenvUnknown{\unexpanded\expandafter{\myenvUnknown,#1}}
    ,protected unknown code =
      \edef\myenvUnknown{\unexpanded\expandafter{\myenvUnknown,#1= {#2}}}
    % some auxiliary keys to restore the unknown list to empty
    ,protected noval clear-unknowns = \let\myenvUnknown\empty
    % initialise the empty unknown-list
    ,initial clear-unknowns
  }

\newenvironment{myenv}[1]
  {%
    \ekvset{myenv}{#1}%
    \expanded{\unexpanded{\begin{tcolorbox}}\expandafter}%
      \expandafter[\myenvUnknown]%
  }
  {%
      \tcblower
      blubb: \myenvBlubb\\
      foo: \myenvFoo\\
      bar: \myenvBar\\
    \end{tcolorbox}%
  }

\begin{document}
\begin{myenv}{colback=blue!30!white,bar=EC,title=example, foo=Foobar}
  This is an example.
\end{myenv}
\end{document}

Another approach can be to use a key=value implementation that supports setting only known keys and storing the unknown keys in a list by using some special syntax (this doesn't require you to code the list-building yourself as done above). One such implementation is l3keys with its \keys_set_known:nnN.

\documentclass{article}

\usepackage{tcolorbox}

\ExplSyntaxOn
\tl_new:N \l__myenv_unknown_tl
\keys_define:nn { myenv }
  {
     blubb .tl_set:N = \l__myenv_blubb_tl
    ,foo   .tl_set:N = \l__myenv_foo_tl
    ,bar   .tl_set:N = \l__myenv_bar_tl
  }
\newenvironment{myenv}[1]
  {%
    \keys_set_known:nnN { myenv } {#1} \l__myenv_unknown_tl
    \exp_last_unbraced:NnNo \begin { tcolorbox } [ \l__myenv_unknown_tl ]
  }
  {%
      \tcblower
      blubb:~ \l__myenv_blubb_tl\\
      foo:~ \l__myenv_foo_tl\\
      bar:~ \l__myenv_bar_tl\\
    \end{tcolorbox}%
  }
\ExplSyntaxOff

\begin{document}
\begin{myenv}{colback=blue!30!white,bar=EC,title=example, foo=Foobar}
  This is an example.
\end{myenv}
\end{document}

Both code blocks give identical results:

enter image description here

You must log in to answer this question.

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