1

I would like to pass user-defined keys. But when the user does not specify values, the default values are used. I need some explanation on what to do in the \setdimensions command. What does .initial work out exactly ?

\documentclass{article}

\ExplSyntaxOn

% Define dimension variables \dim_new:N \l_mymodule_width_dim \dim_new:N \l_mymodule_height_dim \dim_new:N \l_mymodule_margin_dim

% Define a new key-value family \keys_define:nn { mymodule } { width .dim_set:N = \l_mymodule_width_dim, width .initial:n = 34pt, width .default:n = 34pt,

height .dim_set:N = \l_mymodule_height_dim,
height .initial:n = 34pt,
height .default:n = 34pt,

margin .dim_set:N = \l_mymodule_margin_dim,
margin .initial:n = 34pt,
margin .default:n = 34pt,

}

% Command to use the keys \NewDocumentCommand{\setdimensions}{o} { % Use the dimensions in your document or perform other actions \fbox { Width: \dim_use:N \l_mymodule_width_dim \ Height: \dim_use:N \l_mymodule_height_dim \ Margin: \dim_use:N \l_mymodule_margin_dim } }

\ExplSyntaxOff

\begin{document}

% Example usage \setdimensions{ width = 8cm, height = 4cm, margin = 1.5cm, }

\end{document}

Ragonese
  • 171
  • 4
  • 2
    default is the value you would get from \setdimensions{width} . I have some doubts that it makes much sense here. – Ulrike Fischer Feb 29 '24 at 15:09
  • It would be interesting for me to see a version that takes advantage of all the possibilities of using the keys. – Ragonese Feb 29 '24 at 15:11
  • 2
    this is all documented, initial sets thevalue at the point you use \keys_define:nn and default is the value used if you use the key with no =value. – David Carlisle Feb 29 '24 at 15:20
  • 1
    it's not clear what your examle is supposed to be showing, you do not use the keys anywhere, just typeset the input list – David Carlisle Feb 29 '24 at 15:22
  • 1
    also you have declared your command with a single optional argument so { width = 8cm, height = 4cm, margin = 1.5cm, } is not an argument to the command, it is simply text typeset after the command has finished. – David Carlisle Feb 29 '24 at 15:25
  • I want to set the values for the variables using the contents of the keys when calling the command. – Ragonese Feb 29 '24 at 15:39
  • 1
    @Ragonese that's what I show in my answer, your code declares some keys but never sets them to any values (other than the initial values you set at declaration) – David Carlisle Feb 29 '24 at 15:47
  • I want to figure out how to set the variables using the capabilities of the key-value system for the command. I have to call \keys_set:nn but was wondering how that should be used. – Ragonese Feb 29 '24 at 15:48
  • 1
    as I showed in my answer, but first you need to learn the basics of defining commands in latex, just putting some key=value in a text stream does not magically make them an argument of a command, you need to define the command to take an argument and use that argument #1 to do whatever you want (set keys in this case) – David Carlisle Feb 29 '24 at 15:51

3 Answers3

3

Your question is not really clear enough to answer, but I'll try...

The code produces

enter image description here

The text in a box has no space as it is set up in \ExplSyntaxOn and it just shows the values of the three registers which are set by the initial key as those values are set when the keys are defined, and you never set any keys after that.

The command is defined to have one optional argument which it never uses, so the argument would be used inside [...] so the following tokens

{
  width = 8cm,
  height = 4cm,
  margin = 1.5cm,
}

are not seen by the command at all, and are just typeset as text, as shown in the above image.


I would guess you intended

enter image description here

Where the command is defined to take an argument which is used to set the key values. The key settings are contained in a local group so will not be changed after the command.

\documentclass{article}

\ExplSyntaxOn

% Define dimension variables \dim_new:N \l_mymodule_width_dim \dim_new:N \l_mymodule_height_dim \dim_new:N \l_mymodule_margin_dim

% Define a new key-value family \keys_define:nn { mymodule } { width .dim_set:N = \l_mymodule_width_dim, width .initial:n = 34pt, width .default:n = 34pt,

height .dim_set:N = \l_mymodule_height_dim,
height .initial:n = 34pt,
height .default:n = 34pt,

margin .dim_set:N = \l_mymodule_margin_dim,
margin .initial:n = 34pt,
margin .default:n = 34pt,

}

% Command to use the keys \NewDocumentCommand{\setdimensions}{m} { \group_begin: \keys_set:nn{mymodule}{#1} % Use the dimensions in your document or perform other actions \fbox {\begin{tabular}{l} Width: \dim_use:N \l_mymodule_width_dim \ Height: \dim_use:N \l_mymodule_height_dim \ Margin: \dim_use:N \l_mymodule_margin_dim \end{tabular} } \group_end: }

\ExplSyntaxOff

\begin{document}

% Example usage \setdimensions{ width = 8cm, height = 4cm, margin = 1.5cm, }

\end{document}

David Carlisle
  • 757,742
  • 1
    Does just having \keys_set:nn{mymodule}{#1} allow all the capabilities of using the keys through calling the command ? – Ragonese Feb 29 '24 at 15:45
  • 1
    @Ragonese I have no idea what you mean sorry, \keys_set:nn is how you use keys, you had not used the keys at all. – David Carlisle Feb 29 '24 at 15:46
  • I want to call the command with all the possibilities provided by the keys. Meaning 1) with user-defined values, 2) with default values, 3) with initial values, – Ragonese Feb 29 '24 at 15:50
  • 1
    @Ragonese that is what this does. What is your question? – David Carlisle Feb 29 '24 at 15:53
  • How would I call \setdimensions{ to use the initial values in keys ? – Ragonese Feb 29 '24 at 15:55
  • 1
    \setdimensions{} of course. If you have not changed the values you get the initial value, it's just the natural meaning of initial value. – David Carlisle Feb 29 '24 at 15:58
  • Why do you group the code exactly, using {{ and }}, rather than just { and } only ? – Ragonese Mar 01 '24 at 03:43
  • @Ragonese the outer braces are not a group, they delimit the argument of the definition. – David Carlisle Mar 01 '24 at 08:03
  • I am referring to {{ just before \keys_set:nn{mymodule}{#1}. – Ragonese Mar 01 '24 at 11:35
  • @Ragonese yes exactly: the first { is delimiting the argument of \NewDocumentCommand the second starts a scoping group to keep the key setting local. In his version egreg moved the settings inside the fbox so they are already local to that box but if you removed the fbox you would need to add a group somewhere as I show here. – David Carlisle Mar 01 '24 at 11:47
  • @Ragonese compare \def\foo{ \bfseries abc} \foo xyz and \def\foo{{ \bfseries abc}} \foo xyz in the first xyz is bold as the font change is not in a group, in the second xyz is not bold. – David Carlisle Mar 01 '24 at 11:49
  • @DavidCarlisle please use \group_begin:...\group_end: for code-level groups instead of {...} in L3 as per convention. – Skillmon Mar 02 '24 at 22:17
  • @Skillmon yes I guess that would make the distinction clearer, I'll update – David Carlisle Mar 02 '24 at 23:19
1

If you'd rather make the argument optional, so you can just say \setdimensions to use the initial values, you can do that provided you write \setdimensions[<list of key-values>] with square rather than curly brackets.

For example,

\documentclass{article}

\ExplSyntaxOn

% Define a new key-value family \keys_define:nn { mymodule } { width .dim_set:N = \l_mymodule_width_dim, width .initial:n = 34pt, width .default:n = 10pt,

height .dim_set:N = \l_mymodule_height_dim, height .initial:n = 34pt, height .default:n = 10pt,

margin .dim_set:N = \l_mymodule_margin_dim, margin .initial:n = 34pt, margin .default:n = 10pt, }

% Command to use the keys \NewDocumentCommand{\setdimensions} { O{} } { % Use the dimensions in your document or perform other actions \fbox { \keys_set:nn { mymodule } { #1 } \begin{tabular}{ll} Width: & \dim_use:N \l_mymodule_width_dim \ Height: & \dim_use:N \l_mymodule_height_dim \ Margin: & \dim_use:N \l_mymodule_margin_dim \end{tabular} } }

\ExplSyntaxOff

\begin{document}

% Example usage With custom values:

\setdimensions[% width = 8cm, height = 4cm, margin = 1.5cm, ]

With initial values:

\setdimensions

With default values:

\setdimensions[width,height,margin]

\end{document}

produces

custom, initial and default values

Whether this is the kind of example using the different values you wanted, I'm not sure ....

cfr
  • 198,882
  • What would be the reason for choosing O{} over o ? – Ragonese Feb 29 '24 at 19:10
  • @Ragonese You could use o. Then you'd need to test \IfValueTF {#1} {\keys_set:nn {mymodule} {#1}}{\keys_set:nn {mymodule} {}}. It would be different if you weren't using initial values because then you could just skip setting the keys if the option wasn't used. But you want the initials, so it seemed easier to just pass a default empty value. – cfr Feb 29 '24 at 19:14
  • Then if it is empty, initial gets applied. And If I do not use initial I would only do \IfValueT {#1} {\keys_set:nn {mymodule} {#1}}. Correct ? – Ragonese Feb 29 '24 at 21:37
  • @Ragonese If you don't use initial and you use o in place of O{}, then, yes, use the \IfValue... stuff. But you will want to make sure you have fallback values defined somehow. But you could just do \dim_set:Nn \l_mymodule_width_dim {20pt} or whatever in the preamble for that. – cfr Feb 29 '24 at 21:52
  • When not setting initial values, the call to \setdimensions uses values of 0.0pt. Would this how things should be, using values of 0.0pt for dimensions when not setting tho key values ? – Ragonese Mar 01 '24 at 03:19
  • @Ragonese If you don't set initial values and don't use \dim_set:Nn ... to initialise them then, yes, they'll be 0. – cfr Mar 01 '24 at 04:25
  • @Ragonese beware, there is a misconception. If the argument is empty the current values in your variables will be used, not necessarily the .initial:n once. .initial:n only sets the values once at point of use, it doesn't add any hooks or whatnot to magically reset those values later. So in fact O{} with \keys_set:nn {mymodule} {#1} and o with \IfValueT {#1} { \keys_set:nn {mymodule} {#1} are equivalent, they both do nothing if you omit the optional argument. – Skillmon Mar 01 '24 at 11:10
  • @Skillmon But in this case, the values are being set within a local group. It is true that if you change them at the top level, those values will override the initial ones. But you're right that I forgot the initial values get set when you define them, as opposed to when they are used. So it makes no odds which form of o/O, as you say. But the current values will always be the initial ones if you only set them using \mydimensions or another macro which sets them only locally. – cfr Mar 02 '24 at 05:43
  • @cfr absolutely correct. I just wanted to make sure OP knows the difference; my comment was regarding "Then if it is empty, initial gets applied", which is wrong or at least misleadingly formulated. Even if OP knew the difference it could confuse future visitors. – Skillmon Mar 02 '24 at 12:51
  • @Skillmon Agreed. And I was definitely contributing to that confusion. – cfr Mar 02 '24 at 19:24
0

This answer just aims to clear up a few details, not provide some code you can run.

Since the key-defining and key-setting is separated in l3keys you'd have to run a separate \keys_set:nn to set a first/initial value. Since this is cumbersome and separates the key declaration from its initialisation, the .initial:n handler was added.

All that handler does is set a key to a value (so in essence <key> .initial:n = { <value> } inside of \keys_define:nn { <module> } is the same as if you'd put a \keys_set:nn { <module> } { <key> = { <value> } } at that point, it doesn't add anything else to the key code. So any later setting of that key (outside of a nested group) will overwrite that .initial:n value, and it's impossible to get it back if it hasn't been manually recorded through different means.

Skillmon
  • 60,462