8000 Add support for key value expansion by josephwright · Pull Request #1769 · latex3/latex3 · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add support for key value expansion #1769

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open

Conversation

josephwright
Copy link
Member
@josephwright josephwright commented Jul 2, 2025

This is part one of addressing latex3/latex2e#1801 - I also need to do the template code in the 2e repo.

I've chosen to go for the 'higher level' l3keys rather than \keyval_parse:nnn, as the latter is meant to be entirely generic, so to me feels like expansion control is down the programmer there.

I expect to write something for ltnews but will do that as part of the PR for template code; I may also look at adding something to usrguide at that point (but that's more tricky as this doesn't affect all keyvals provided by the base distro. most obviously the classical keyval pkg).

I've gone for performance over allowing : in key names - I hope this minor restriction is not too much of an issue as a breaking change.

Copy link
Member
@FrankMittelbach FrankMittelbach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some minor comments

@@ -774,6 +774,23 @@
% is not processed in any way by \cs{keys_set:nn}.
% \end{variable}
%
% \subsection{Expanding the values of keys}
%
% To allow the user to apply value expansion at point-of-use, key names can be
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

already at the time the key is set (and not later when it is used), % or something

I find point-of-use difficult to understand as the "usage" seems to happen later not then

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to contrast with a key where the expansion is 'built-in', so e.g. \tl_set_e:N or similar - suggestions on wording welcome.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

normally key values aren't expanded at time of setting and all this expansion stuff is there precisely when no expansion happens. I thought I gave a suggestion. Not good?

% \keys_set:nn { mymodule } { key : v = { l_mymodule_value_tl } }
% \keys_set:nn { mymodule } { key : e = \exp_not:V \l_mymodule_value_tl }
% \end{verbatim}
% all pass \texttt{value} to the key handler.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that would then need some adjustment of course

Comment on lines 3781 to 3782
Key~values~can~only~be~expanded~using~one~of~the~pre-defined~methods:~
n,~o,~V,~v~or~e.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c might be useful here too? (given that we support v)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't really make sense - we are expanding n-type tokens - as I've said, we are in the end storing a token list in the first instance, so the expansion behaviours available do not include c. Also, really would be odd to do key:c = value rather than just key = \value.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that depends on what "\value" is, it may contain chars that you can't just write behind a backslash but you need c expansio nto construct it. For example a use who want to have @secntformat as a value. Not insisting but it is similar to supporting v in addition to V (same reason)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see your point re. v, but my take is to omit that :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josephwright I'm not sure why you say c wouldn't make sense? It would make sense in the same way that c generally makes sense wouldn't it? supporting all the L3 letters seems simpler than subsetting here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Key values are strings, so are (more-or-less) n-type - you can therefore o-, V-, v-, e-, f- or x-type expand them, but not c-type. v-type feels rather odd to do, and we don't really want to encourage new f- or x-type usage, hence I've omitted those from the message by design.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Key values are strings, [...]

Not l3str string, but n-type parameter.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I do mean here the general programming idea of a string - so for us a tl.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First: Key values are not strings, they are token lists in their most abstract form! (as already established)

Second: Subsetting is more work than simply allowing all variants (make sure it's a single token, stringify and do \cs_if_exist_use:cTF { exp_args:N #1 }.

Third: There might be valid keys that only take a single token in user land, which might be enforced by additional checks in the user code. For instance a key allowing to define the control sequence in which to store the results of some operation. Here :c would be helpful.

% \tl_set:Nn \l_mymodule_value_tl { value }
% \dime_set:N \l__mymodule_value_dim { 123pt }
% \keys_set:nn { mymodule } { key = value }
% \keys_set:nn { mymodule } { key : o = \l_mymodule_value_tl }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think here it would be better to show no space around the : spaces work here but just because of L3 syntax, you could equally spell the key name as k e y with spaces. Unlike defining the keys, setting them is often, perhaps usually, lifted up to a document level command and there you need key:e with no space (unless we want to take the cost of removing spaces by hand.)

\documentclass{article}

\begin{document}

\ExplSyntaxOn
\keys_define:nn {me} {
  k .tl_set:N  = \l_me_foo_tl
}

\def\myset{\keys_set:nn {me}}
\def\myshow{\show\l_me_foo_tl}
\ExplSyntaxOff

\def\qq{88}

%\myset{k :e=\qq} %expansion ' e' unknown
%\myset{k :e=\qq} %key 'me/k' unknown
%\myset{k : e=\qq} %expansion ' e' unknown
\myset{k:e=\qq} % works
\myshow

\end{document}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could do that, or I could zap the spaces ... thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the analogy with csname suffixes is stronger if you use :e with no space so I'd be happy to document that form, but in all the other kv parsing I suppose an extra pass to lose space here is another possibility if people want to write key : e (or could you lose the spaces in the same pass, so ignoring spaces was "free"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed the docs; we do have 'trim spaces only one side' functions, so if we wish to revisit later, the cost of space trimming isn't a disaster.

Copy link
Member
@FrankMittelbach FrankMittelbach Jul 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer not show spaces between around the : . In my opinion the syntax should be key:char regardless of the fact that within ExplSyntaxOn you can in fact always write m yk ey : e or worse to mean mykey:e

Copy link
Member
@FrankMittelbach FrankMittelbach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still think that c an v are useful, but that can wait until you get user requests :-)

Copy link
Collaborator
@muzimuzhi muzimuzhi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typos and a bit more.

Comment on lines +3222 to 3237
\cs_new_protected:Npe \@@_find_key_module_auxiv:Nw
#1 #2 \s_@@_nil #3 \s_@@_mark
\s_@@_nil \@@_find_key_module_auxiv:Nw #4
{
\cs_set_nopar:Npn #4 { #2 }
\exp_not:N \@@_find_key_module_auxv:Nw #4
#2 \token_to_str:N : n \token_to_str:N : \s_@@_mark
}
\use:e
{
\cs_new_protected:Npn \exp_not:N \@@_find_key_module_auxv:Nw
#1 #2 \token_to_str:N : #3 \token_to_str:N : #4 \s_@@_mark
}
{
\cs_set_nopar:Npn #1 {#2}
\cs_set_nopar:Npn \l_@@_exp_str {#3}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\token_to_str:N : can be replaced with \c_colon_str.

Or, these two function definitions can be wrapped in \@@_tmp:w, then actually defined by \exp_args:No \@@_tmp:w { \c_colon_str }.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but I don't know this is any clearer

Co-authored-by: Yukai Chou <muzimuzhi@gmail.com>
Comment on lines +779 to +780
% To allow the user to apply expansion of values when the key is set, rather
% than when they are used, key names can be
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still find the distinction with "use" strange. What does "use" mean? The key isn't used when the (internal) variable, which was set to the value given, is used, the variable is used then. So what is key usage?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants
0