# How can I recover option values with the current l3keys2e?

Minimal-Compiling-But-Not-Working Example:

\begin{filecontents}{\jobname.cls}

\ProvidesClass{\jobname}

\RequirePackage{l3keys2e}

\ExplSyntaxOn
\keys_define:nn { job / doc }
{
doc~name .tl_set:N = \l_job_doc_name,
}

\ProcessKeysOptions { job / doc }

\ExplSyntaxOff

\PassOptionsToClass{10pt}{article}
\DeclareOption*{%
\PassOptionsToClass{\CurrentOption}{article}
}
\ProcessOptions

\ExplSyntaxOn
\AtBeginDocument{
This ~ document's ~ name ~ is ~ \l_job_doc_name .\par
}
\ExplSyntaxOff
\endinput
\end{filecontents}

\documentclass[doc name=ben]{\jobname}
\begin{document}
hello
\end{document}


I would expect this to give me 'This document's name is ben.' then a new line, then 'hello'. However, that doesn't happen any longer, although (a much more complex version of) this code used to work.

• The compilation complains about doc name being an unknown option – user31729 Jan 26 '18 at 19:12
• @ChristianHupfer Yes. It no longer permits spaces in key names. Eek. – cfr Jan 26 '18 at 19:17
• @ChristianHupfer Mind you, it always complains about them being unknown options, even when they are known and don't have spaces and work fine. So that in itself doesn't mean much, I guess. – cfr Jan 26 '18 at 19:18
• I wonder that it ever did. – user31729 Jan 26 '18 at 19:18
• Try \documentclass[10pt,{doc name=ben}]{\jobname} – user31729 Jan 26 '18 at 19:29

Your problem is that the LaTeX kernel removes spaces from the global option list before it's passed to any further code. As such, l3keys2e sees docname=ben which is a different key name to doc name. The safest solution here is to not use spaces in key names.

• Thanks, I know that is why, but what changed? This worked before. – cfr Jan 26 '18 at 23:09
• Is this now true for all l3 keys or does the change only affect l3keys2e? If the former, that's a lot worse in terms of the number of changes required to fix the many documents this will break. If the latter, it will break just as many documents, but they won't be quite as badly broken. – cfr Jan 26 '18 at 23:12
• @cfr It's a general change, but really it shouldn't affect many documents: the LaTeX2e kernel has never supported spaces in the optional argument to \documentclass or \usepackage, whilst I'd hope that most key uses in other contexts have well-defined names (so foo bar or foobar). – Joseph Wright Jan 27 '18 at 8:07
• I really meant, does it affect the handling of all key names with spaces in l3, or only those passed from class/package options? The first case is going to break more-or-less the same number of documents for me (lots), but much less seriously. And working around it is much less work. I'm guessing from your example that foo~bar will still accept foo bar when not used in class/package options? – cfr Jan 27 '18 at 23:31

Apparently, this is an intended change:

We used to normalise out spaces entirely, but there were some issues so that's been dropped. -- Joseph Wright

So the breakage is a new feature ;).

Since the problem is that the space is normalised away from the options passed to the class/package, but not the options defined in the class/package, I guess the easiest way to deal with the change to the code which l3keys2e sees is to remove the space in the class/package definition. The spaces in documents can be left, as they will be normalised away to match the key names in the package/class before the l3keys2e code sees them.

That is, I can write

 \keys_define:nn { job / doc }
{
doc name .tl_set:N = \l_job_doc_name,
}


and then

\documentclass[doc name=ben]{\jobname}


will work as expected: in both cases, the space will disappear and everything will match up properly. So

\ProcessKeysOptions { job / doc }


will match docname with docname and l3keys2e will know my document is named ben.