As far as I am aware, there is no mechanism in l3keys
to preset keys like the xkeyval
supports.
I explicitly do not mean the .default:n
specification in l3keys
, since this is invoced if the key
is given but no =value
is present.
With the following definition
\keys_define:nn { module }
{
keya .tl_set:N = \l_keya_tl,
keya .default:n = { foo },
keyb .tl_set:N = \l_keyb_tl,
keyb .default:n = { bar },
}
the invocation \keys_set:nn { module } { keya }
will set \l_keya_tl
to foo, as this is
the default value. But I would like \keys_set:nn { module } { }
to also change the value of the \l_keya_tl
variable, e.g. to \c_novalue_tl
so that after setting the keys, I can differentiate between
- the user has not given the key at all (no value supplied)
- the user set the key (with or without an
=
, this is handled by the.default:n
)
Currently, I just run \tl_set_eq:NN \l_key_tl \c_novalue_tl
before setting the keys,
then I can test if the user gave the key with
\tl_if_novalue:VTF \l_my_tl { no value specified } { handle user value }
and of course this works just fine.
Is it a design choice to not provide such features in l3keys
(e.g. because they are considered poor style), or is this just not implemented as it is not needed often?
Also note that this beahviour is very similar to using .initial:n
and then use grouping to set keys locally whenever setting them, so that the initial:n
never changes. This is, however, not an option for me in some situations.
Currently my approach is to just manually execute an additional \keys_set:nn { module } { keys, to, preset }
, and then setting the user keys, but this seems tedious.
From what gusbrs pointed out, I get that with How to distinguish "no value" from "empty value" when setting `l3keys`? can distinguish the situations
\keys_set:nn { module } { keya, keyb = bar }
, where the key has been set and no value is provided at all. This will be handled by.default:n
, which is - if present, equivalent to having calledkeya = <default>
\keys_set:nn { module } { keya=, keyb = bar }
, where the key has been explicitly set, but to the empty token list.keys_set:nn { module } { keya = foo, keyb = bar}
, where we regularly set a value
What I want is to also detect the
\keys_set:nn { module } { keyb = bar }
situation, in which case I would e.g. also want to execute the.default:n
handler (for types that don't support the absence of a value), but in the case of a token list also be able to execute\tl_set_eq:NN \l_keya_tl \c_novalue_tl
in this case.
I could imagine this to be handled by some kind of .preset:n
property that gets executed *every time keys are set for this module` before processing the keys, no matter what keys are given.
This would
- guarantee that there is actually a value after setting the keys
- also handle the token list case by specifying
.preset:V = \c_novalue_tl
, which would yield my desired behaviour.
Have a look at the section on 'Presetting keys' in the xkeyval
documentation, this is what I intend to have.
l3keys
concept is that there is no such thing as a key having no value: they exist once you create them and may have an empty value.int
, you need to be able to use the value whether it's set or not.\foo[key1 = val1, key2 = val2]{something}
, and ifkey2
has not been given, we use some kind of fallback, so the key behaves like an optional argument?0
in case the key is not specified. This way we make sure that the int has a value, but we don't just end up using the int value from the previous invocation, which could be anything.