निरंजन
I combined the two answers received on [this](https://topanswers.xyz/tex?q=8074) question. `l3`fied the code and have created an `expkv`+`latex3` interface. One new feature is added. It's nearly working, but there are two macros that are not expanding where I want them to. I am failing to understand why. I have the following three expectations.
1. `\l__my_field_tl` and `\l__my_type_tl` work in one segment of my `l3msg` (cf. `field` and `type` entries from the generated log), but fail in the `nfss` entry. I am guessing it's a grouping (local vs. global) problem, but I don't understand how. I start one group in the `meta` key `article` and end it after all the other processing is finished as everything else is inside its scope.
2. `\l__my_font_print_tl` and `\l__my_font_options_print_tl` are not expanding in the message command at all. They need to tell me the font name and loaded font options (as the names suggest). I am pretty sure that the options will be too many, so is there any way I can preprocess them and instead of commas+randomly wrapped text like:
```
(my) options: Color=red,Renderer=HarfBuzz,
(my) BoldFont=KpSans-Bold.otf
```
I would like to add a line-break and some extra spaces, like:
```
(my) options: Color=red,
(my) Renderer=HarfBuzz,
(my) BoldFont=KpSans-Bold.otf
```
Would require some extra processing, but if its not too much of a burden, I would love to try it.
3. Finally and most importantly, the font is not getting set with the font command! It was getting set before I got into `l3`-fication. Now I don't know where I exactly made the mistake. Here is the code I have created:
```
\documentclass{article}
\usepackage{fontspec}
\usepackage{expkv}
\usepackage{xcolor}
\ExplSyntaxOn
\seq_new:N \l__my_font_options_seq
\seq_new:N \l__my_type_seq
\tl_new:N \l__my_field_tl
\tl_new:N \l__my_type_tl
\tl_new:N \l__my_meta_tl
\tl_new:N \l__my_font_print_tl
\tl_new:N \l__my_font_options_print_tl
\msg_new:nnn { my } { font } {
A~ font~ has~ been~ successfully~ set:\\
\tl_if_empty:NF \l__my_meta_tl {
meta:\ \ \ \ \ \l__my_meta_tl\\
}
cs:\ \ \ \ \ \ \ \c_backslash_str #1\\
field:\ \ \ \ \l__my_field_tl\\
type:\ \ \ \ \ \l__my_type_tl\\
font:\ \ \ \ \ #2\\
nfss:\ \ \ \ \ #3\\
options:\ \ #4
}
\cs_new_protected:Npn \__my_new_font_family:Nnn #1#2#3 {
\newfontfamily {#1} [#2] {#3}
}
\cs_generate_variant:Nn \__my_new_font_family:Nnn { ce }
\cs_new_protected:Npn \__my_process_font:n #1 {
\seq_set_split:Nnn \l__my_font_options_seq
{ ; }
{ #1 }
\__my_new_font_family:cen {
__ my
_ \l__my_field_tl
_ \l__my_type_tl
_ font
} {
\seq_item:Nn \l__my_font_options_seq { 2 },
NFSSFamily = {
my
_ \l__my_field_tl
_ \l__my_type_tl
_ nfss
}
} {
\seq_item:Nn \l__my_font_options_seq { 1 }
}
\tl_set:Ne \l__my_font_print_tl {
\seq_item:Nn \l__my_font_options_seq { 2 }
}
\tl_set:Ne \l__my_font_options_print_tl {
\seq_item:Nn \l__my_font_options_seq { 1 }
}
\seq_put_right:NV \l__my_type_seq \l__my_type_tl
}
\cs_new_protected:Npn \__my_set_fonts:n #1 {
\cs_gset:cpn { __ my _ #1 _ fonts } {
\seq_map_inline:Nn \l__my_type_seq {
\cs_set:cpn { ####1default }
{ my #1 _ ####1 _ nfss }
}
\normalfont
}
\msg_note:nnnnnn { my }
{ font }
{
__ my _ #1 _ fonts
}
{
\l__my_font_print_tl
}
{
my
_ \l__my_field_tl
_ \l__my_type_tl
_ nfss
}
{
\l__my_font_options_print_tl
}
}
\clist_map_inline:nn {
article,book
}{
\protected \ekvdef { my-initial } { #1 } {
\group_begin:
\tl_set:Nn \l__my_meta_tl { #1 }
\ekvset { my-initial } { ##1 }
\group_end:
}
}
\clist_map_inline:nn {
title,
subtitle
} {
\protected \ekvdef { my-initial } { #1 } {
\__my_seq_clear:
\tl_if_empty:NTF \l__my_meta_tl {
\tl_set:Nn \l__my_field_tl { #1 }
} {
\tl_set:Ne \l__my_field_tl {
\l__my_meta_tl _ #1
}
}
\ekvset { my-vital } { ##1 }
\exp_args:Ne \__my_set_fonts:n { \l__my_field_tl }
}
}
\clist_map_inline:nn {
rm,
sf,
tt
} {
\protected \ekvdef { my-vital } { #1 } {
\tl_set:Nn \l__my_type_tl { #1 }
\__my_process_font:n { ##1 }
}
}
\cs_new:Nn \__my_seq_clear: {
\seq_clear:N \l__my_mathrm_seq
\seq_clear:N \l__my_font_options_seq
\seq_clear:N \l__my_type_seq
}
\ExplSyntaxOff
\NewDocumentCommand \setup { m } {%
\ekvset{my-initial}{#1}
}
\begin{document}
\setup{
article = {
title = {
rm = {
KpRoman-Regular.otf;
Color = {blue}
}
}
},
subtitle = {
sf = {
KpSans-Regular.otf;
Color = {red}
}
}
}
\ExplSyntaxOn
\__my_article_title_fonts
\ExplSyntaxOff
abcd
\end{document}
```
Connected to this, I also want a general advise on whether I should expand the font-options like this in public packages? Do you see any risks in it? As a side note: The `<font>;<font-opts>` syntax is not for any public releases. I myself don't like it much, but for a privately collaborated project, I need it. But the other question regarding the expansion of font options is generic.
Top Answer
Skillmon
You have the same issue you had last time: `\seq_map_inline:Nn \l__my_type_seq` is only executed when `\l__my_type_seq` is empty due to grouping (I switched to `\seq_map_function:NN` and expansion where it is used by using `\cs_gset:cpx`). Also you got inconsistent grouping problems (I removed the groups and instead manually clear `\l__my_meta_tl`). If you're using either `article` or `book` as the top level in your setup command you get groups, if you directly pick either `title` or `subtitle` there are no groups. Even if `\l__my_type_seq` wasn't empty you would have an `_` missing after `my`. And you mixed up the sequence items of `\l__my_font_print_tl` and `\l__my_font_options_print_tl`.
I tried copying your indentation style, I hope I got it right everywhere...
```
\documentclass{article}
\usepackage{fontspec}
\usepackage{expkv}
\usepackage{xcolor}
\ExplSyntaxOn
\seq_new:N \l__my_font_options_seq
\seq_new:N \l__my_type_seq
\tl_new:N \l__my_field_tl
\tl_new:N \l__my_type_tl
\tl_new:N \l__my_meta_tl
\tl_new:N \l__my_font_print_tl
\tl_new:N \l__my_font_options_print_tl
% sorry I inserted a bunch of spaces here, I found it easier to spot the
% alignment this way since every space takes two characters as well.
\msg_new:nnn { my } { font } {
A~ font~ has~ been~ successfully~ set:\\
\tl_if_empty:NF \l__my_meta_tl {
m e t a : \ \ \ \ \ \l__my_meta_tl\\
}
c s : \ \ \ \ \ \ \ \c_backslash_str #1\\
f i e l d : \ \ \ \ \l__my_field_tl\\
t y p e : \ \ \ \ \ \l__my_type_tl\\
f o n t : \ \ \ \ \ #2\\
n f s s : \ \ \ \ \ #3\\
o p t i o n s : \ \ #4
}
\cs_new_protected:Npn \__my_new_font_family:Nnn #1#2#3 {
\newfontfamily {#1} [#2] {#3}
}
\cs_generate_variant:Nn \__my_new_font_family:Nnn { ceV }
\cs_new_protected:Npn \__my_process_font:n #1 {
\seq_set_split:Nnn \l__my_font_options_seq
{ ; }
{ #1 }
\tl_set:Ne \l__my_font_print_tl {
\seq_item:Nn \l__my_font_options_seq { 1 }
}
\tl_set:Ne \l__my_font_options_print_tl {
\seq_item:Nn \l__my_font_options_seq { 2 }
}
\__my_new_font_family:ceV {
__ my
_ \l__my_field_tl
_ \l__my_type_tl
_ font
} {
\exp_not:V \l__my_font_options_print_tl,
NFSSFamily = {
my
_ \l__my_field_tl
_ \l__my_type_tl
_ nfss
}
}
\l__my_font_print_tl
\seq_put_right:NV \l__my_type_seq \l__my_type_tl
}
\cs_new:Npn \__my_prettyprint_font_options: {
\tl_if_empty:NF \l__my_font_options_print_tl {
% fully expand the _key:n and _pair:nn auxiliaries
\exp_last_unbraced:Ne
% remove the leading ^^J,<spaces> from the first item
\use_iii:nnn {
% expand \keyval_parse:nnV to a list of _key:n and _pair:nn calls
\use:e {
\keyval_parse:nnV \__my_prettyprint_font_options_key:n
\__my_prettyprint_font_options_pair:nn
\l__my_font_options_print_tl
}
}
}
}
\cs_new:Npn \__my_prettyprint_font_options_key:n #1 {
\__my_prettyprint_font_options_indent:
\exp_not:n {#1}
}
\cs_new:Npn \__my_prettyprint_font_options_pair:nn #1#2 {
\__my_prettyprint_font_options_indent:
\exp_not:n { \exp_not:n {#1} } ~=~ { \exp_not:n { \exp_not:n {#2} } }
}
\cs_new:Npx \__my_prettyprint_font_options_indent: {
,^^J \prg_replicate:nn {10} { ~ }
}
\cs_new:Npn \__my_set_fonts_aux:n #1 {
\cs_set:Npn \exp_not:c { #1 default }
{ my _ \exp_not:V \l__my_field_tl _ \exp_not:n {#1} _ nfss }
}
\cs_new_protected:Npn \__my_set_fonts:n #1 {
\cs_gset:cpx { __ my _ \l__my_field_tl _ fonts } {
\seq_map_function:NN \l__my_type_seq \__my_set_fonts_aux:n
\exp_not:N \normalfont
}
\msg_note:nneeee { my }
{ font }
{ __ my _ \exp_not:n {#1} _ fonts }
{ \l__my_font_print_tl }
{
my
_ \l__my_field_tl
_ \l__my_type_tl
_ nfss
}
{ \__my_prettyprint_font_options: }
}
\clist_map_inline:nn {
article,book
}{
\protected \ekvdef { my-initial } { #1 } {
\tl_set:Nn \l__my_meta_tl { #1 }
\ekvset { my-initial } { ##1 }
\tl_clear:N \l__my_meta_tl
}
}
\clist_map_inline:nn {
title,
subtitle
} {
\protected \ekvdef { my-initial } { #1 } {
\__my_seq_clear:
\tl_if_empty:NTF \l__my_meta_tl {
\tl_set:Nn \l__my_field_tl { #1 }
} {
\tl_set:Ne \l__my_field_tl {
\l__my_meta_tl _ #1
}
}
\ekvset { my-vital } { ##1 }
\exp_args:Ne \__my_set_fonts:n { \l__my_field_tl }
}
}
\clist_map_inline:nn {
rm,
sf,
tt
} {
\protected \ekvdef { my-vital } { #1 } {
\tl_set:Nn \l__my_type_tl { #1 }
\__my_process_font:n { ##1 }
}
}
\cs_new:Nn \__my_seq_clear: {
\seq_clear:N \l__my_mathrm_seq
\seq_clear:N \l__my_font_options_seq
\seq_clear:N \l__my_type_seq
}
\NewDocumentCommand \setup { m } {
\ekvset{my-initial}{#1}
}
\ExplSyntaxOff
\setup{
article = {
title = {
rm = {
KpRoman-Regular.otf;
Color = {blue}
}
}
},
subtitle = {
sf = {
KpSans-Regular.otf;
Color = {red},
}
}
}
\begin{document}
\ExplSyntaxOn
\__my_subtitle_fonts
\ExplSyntaxOff
abcd
\end{document}
```