8

This is an extremely minimal example of what I'm trying to do.

\documentclass{article}
\usepackage{pgfkeys}
\pgfkeys
  {
    /ae/example/set/parameters/.cd,
    keya/.code = { \def\mykeya{#1} },
    keyb/.code = { \def\mykeyb{#1} },
    /ae/example/use/parameters/.cd,
    keya/.code = { \mykeya },
    keyb/.code = { \mykeyb },
  }
\newcommand{\setkeys}[1]{\pgfkeys{ /ae/example/set/parameters/.cd, #1}}
\newcommand{\usekeys}[1]{\pgfkeys{ /ae/example/use/parameters/.cd, #1}}
\pagestyle{empty}
\begin{document}

\setkeys{keya={{\bfseries hello}},keyb={world!}}

\usekeys{keya,keyb} 
This following text should not be \textbf{bold.}

\end{document}

The general idea is that I have setter and getter keys defined. Generally, the macro call is more complicated than just assigning a value to a command name. But the above example illustrates the problem I've run into. My inner braces are getting completely stripped out.

I don't want to assume that key values are to define subgroups. That is, I don't necessarily want to define the key as

/ae/example/set/parameters/.cd,
keya/.code = { \def\mykeya{{#1}} },

I would like the user to be able to specify the grouping by using inner braces like I have in the MWE:

\setkeys{keya={{\bfseries hello}}

I know for the above example I could write

\setkeys{keya={\textbf{hello}}

and everything would be fine. But such an approach won't work for other commands like \footnotesize and other kindred commands. Also, I know I could wrap things up in boxes

\setkeys{keya=\mbox{\bfseries hello}}}

But this prevents the innards of the box from seeing mark-up that's being called from the outside.

Any ideas on how to get pgfkeys to be a bit less greedy in how it strips away braces?

UPDATE

I've considered doing something like:

 \setkeys{keya="\bfseries hello"}

and use some preprocessor to convert the " to the appropriate braces. I also considered defining a variant key like

  /ae/example/set/parameters/.cd,
  keya*/.code = { \def\mykeya{{#1}} },

But I'm wondering whether someone else has a better approach.

A.Ellett
  • 50,533
  • 1
    There is a duplicate here but I cannot find it. The answer is yes that's a bummer. It strips away braces – percusse Jul 06 '13 at 19:41
  • @percusse I suspected that I'd seen something like this posted here previously. But after a couple minutes of searching, I gave up and figured someone else might do a better job on the search. – A.Ellett Jul 06 '13 at 19:44
  • 1
    I'd say this is a flaw in pgfkeys: other key-value packages are very careful about this sort of thing. (Try the same in l3keys and you should see exactly one set of braces stripped.) – Joseph Wright Jul 06 '13 at 19:49
  • @JosephWright l3keys works very nicely and generally does what I want it to do. Where I'm getting stuck with l3keys is creating keys to be processed with private packages. For example, I don't know how to use l3keys to process keys in something like \usepackage[keys={{\bfseries ....}}]{myprivatepackage} I keep getting errors around the use of the equal sign. Perhaps I should post that as its own question? – A.Ellett Jul 06 '13 at 19:53
  • @A.Ellett We have l3keys2e for option parsing, but there is an issue with any keyval processing in package options. The LaTeX2e kernel expands options before passing them on, so things like command names are 'unsafe'. For that reason I've recommended against using load-time options in siunitx and instead promote using \sisetup, even though the 'back-end' is the same. – Joseph Wright Jul 06 '13 at 19:55
  • @JosephWright Should this also be reported as a bug then? – A.Ellett Jul 06 '13 at 21:00
  • @A.Ellett it's not a bug that mostly you can't use keyval options in package options, it simply isn't designed for that (even the original keyval package came out some months after latex2e) If a package wants to add keyval option handling with unexpanded options it either needs a separate setting command as Joseph indicated or it needs to redefine latex's package option code, the latter is highly likely to break other packages, so most choose the former. – David Carlisle Jul 06 '13 at 21:38
  • @A.Ellett I've found the similar (but not dupe) question finally http://tex.stackexchange.com/questions/108162/appending-to-a-style-that-sets-code-with-arguments-in-pgfkeys – percusse Jul 06 '13 at 21:40
  • @DavidCarlisle Sorry, I wasn't clear. I wasn't thinking that complications of passing keyvals through the options of a package was a bug. No! I was thinking that the stripping away of multiple layers of braces was the bug. – A.Ellett Jul 06 '13 at 21:43
  • Oh that is yes:-) – David Carlisle Jul 06 '13 at 21:44

1 Answers1

5

Stripping brace pairs from input is something TeX does 'as standard' if you do something like

\def\foo#1\stop{\detokenize{#1}}
\foo{bar}\stop
\foo{bar} \stop

where you loose the braces in the first case but not the second. This type of code (delimited arguments) is needed quite a bit inside any key-value ('keyval') processor, and so care is needed if you do not want to 'loose' braces accidentally.

It is possible to set up code internally such that a known number of braces are stripped. For example, the LaTeX3 keyval code will strip at exactly one set of braces from input, meaning that

foo = bar

and

foo = {bar}

are equivalent but distinct from

foo = {{bar}}

However, this is not a requirement of creating a keyval package that brace stripping works in this way. Testing the pgfkeys package, it will strip up at least two and up to three sets of braces, depending on the exact location of any spaces in the input. Altering this behaviour would require rewriting parts of pgfkeys, which might have a knock-on effect on other packages using the code: some may implicitly rely on brace removal. Certainly it would be complex to turn such changes 'on and off' (doable, but non-trivial). As such, I would suggest if you do need to be sure of the number of brace pairs stripped you use a keyval package which explicitly documents the outcomes.

You might wish to report this as an issue to the maintainers of pgfkeys, but I am not sure they will regard it as a bug (they don't document that a particular number of braces should be stripped). As I say, altering this might break stuff!

Joseph Wright
  • 259,911
  • 34
  • 706
  • 1,036