3

I've created a custom class with key-value options using pgfopts. So far this is working fine. Now I would like to create a key which can take a random string including equal sign and comma.

The below example will illustrate my needs.

\begin{filecontents}{\jobname.cls}
    \ProvidesClass{\jobname}[2018-11-20 v1.0 SE Test package]
    \RequirePackage{pgfopts}
    \pgfkeys{
        testproj/.cd,
        mystuff/.store in = \myValue,
        mystuff = {} % <-- Set default to empty
    }
    \ProcessPgfOptions{/testproj}
    \LoadClass[\myValue]{article}
    \endinput
\end{filecontents}
% ------------------
\documentclass[mystuff = {hello=SE,test=1}]{\jobname}
%\pgfkeys{/testproj/mystuff = {hello=SE}} % <-- working as aspected
\begin{document}
    myValue: \myValue
\end{document}

The key mystuff should take any string and should be passed as class option. The problem is that mystuff will only take "hello" as argument instead of the whole content inside the parenthesis "hello=SE,test=1".

How can I manage to pass a random string as class option including a equal sign and a comma using pgfopts?

faltfe
  • 519
  • 3
    This is unrelated to pgfopts, but it's a consequence of how the option parser is implemented in LaTeX. The option passes through LaTeX's parser before being passed to pgfopts. The kvoptions-patch package fixes this. You have to load it before the \documentclass. I gave an explanation in the post I linked. The situation is different, but the issue boils down to the same. The problem is not with the = inside the braces, but with the space around the first = sign. – Phelype Oleinik Nov 20 '18 at 18:58
  • 1
    Thanks for your quick answer. Your are completely right that the problem is the space. When I remove the space between the equal sign the whole content is passed. This will serve my needs. – faltfe Nov 20 '18 at 19:08

1 Answers1

2

As requested by Mr. Marmot :)

What is happening here is not related to pgfopts. Any other key-value parser would struggle with the same problem. The LaTeX kernel, by design, strips spaces from options, so that, for instance, \documentclass[12 pt]{article} will mean exactly the same as \documentclass[12pt]{article} (explanation).

The implemented space-removing method plus TeX's argument grabbing rules transform this:

\documentclass[mystuff = {hello=SE,test=1}]{\jobname}

into this:

\documentclass[mystuff=hello=SE,test=1]{\jobname}

which means that the mystuff option will receive hello, and you'll have a stray =SE,test=1 in the option list.

If you, however, use:

\documentclass[mystuff={hello=SE,test=1}]{\jobname}

then the option list is passed correctly, because there was no spaces to remove (again, see the linked post above for a detailed explanation).

LaTeX's argument parser wasn't designed to handle key-value pairs, but simple options which would turn something on or off in the code, so this wasn't a worry at the time.

To fix this there's basically two options:

  • Remove the spaces. Beware that if you leave a space there the options will be misunderstood with no error message (except the Unused global option warning in the log).

  • Load the kvoptions-patch package before the \documentclass (with \RequirePackage{kvoptions-patch}) or before whatever package you are passing the options to. This package re-implements most of LaTeX's option parser, so most of these problems are eliminated.