If you want to split your key=value list into the rows of your table, one would expect a set of possible second level keys that are common for all your top level keys.
The following uses expkv
with the two extensions expkv-def
and expkv-cs
for this. The top level is a typical key=value interface defined with \ekvdefinekeys
. The data
key will store the value and act as a Boolean switch at the same time. If the key was used, the defined macro will expand to its first argument followed by the value provided to the key. If the key wasn't used, the defined macro will expand to its second argument only. We can use this to provide the values to our macro parsing the second layer, which is called \evaluation@row
in this example.
\evaluation@row
is defined with \ekvcSplit
, it'll accept the keys n
, e
, and h
(all with an empty default value), and expand to #1
, #1
being the first key defined in the previous list, #2
to the second, and so on. The neat thing which makes this practical for table cells is that expkv-cs
's key=value interface remains fully expandable.
\documentclass{memoir}
\usepackage{xparse}
\usepackage{expkv-cs,expkv-def}
\makeatletter
% define the top level keys
\ekvdefinekeys{evaluation}
{%
data cc = \evaluation@cc,
data ds = \evaluation@ds,
store project = \evaluation@project
}
\ekvsetdef\evaluation@kv{evaluation}
% define the keys at second level and split them into $n$ & $e$ & $h$
\ekvcSplit\evaluation@row{n=,e=,h=}{#1}
\NewDocumentCommand\Evaluation{O{}}
{%
\begingroup
\evaluation@kv{#1}%
\begin{tabular}{*{4}{c}}
Type & Number & Exam & home work\\
CC & \evaluation@cc\evaluation@row{&&} \\
DS & \evaluation@ds\evaluation@row{&&} \\
$\vdots$\\
\end{tabular}
\endgroup
}
% silently ignore unknown keys in the top level
\ekvdefunknown{evaluation}{}
\ekvdefunknownNoVal{evaluation}{}
% silently ignore unknown keys in the second level
\ekvdefunknown{\string\evaluation@row}{}
\ekvdefunknownNoVal{\string\evaluation@row}{}
\makeatother
\begin{document}
\Evaluation[cc={n=1,e=2,h=3,j=error}, projet={h=8}]
\end{document}
With a few adjustments, we can use the possibilities of the data
key type to also omit the unspecified rows in this variant. The necessary adjustments will be to use \ekvcSplitAndForward
instead of \ekvcSplit
, as the next step will have to grab an additional argument (the name of the row). The second argument of the data
-key defined macros has to be \@gobble
, which will just remove the name of the row.
\documentclass{memoir}
\usepackage{xparse}
\usepackage{expkv-cs,expkv-def}
\makeatletter
% define the top level keys
\ekvdefinekeys{evaluation}
{%
data cc = \evaluation@cc,
data ds = \evaluation@ds,
store project = \evaluation@project
}
\ekvsetdef\evaluation@kv{evaluation}
% define the keys at second level and split them into arguments for
% `\evaluation@row@`. You can specify default values for `n`, `e`, and `h` after
% the equals signs (currently empty).
\ekvcSplitAndForward\evaluation@row\evaluation@row@{n=,e=,h=}
\newcommand\evaluation@row@[4]{#4\\}
\NewDocumentCommand\Evaluation{O{}}
{%
\begingroup
\evaluation@kv{#1}%
\begin{tabular}{*{4}{c}}
Type & Number & Exam & home work\\
\evaluation@cc\evaluation@row\@gobble{CC}%
\evaluation@ds\evaluation@row\@gobble{DS}%
$\vdots$\\
\end{tabular}
\endgroup
}
% ignore unknown keys in the top level
\ekvdefunknown{evaluation}{}
\ekvdefunknownNoVal{evaluation}{}
% ignore unknown keys in the second level
\ekvdefunknown{\string\evaluation@row}{}
\ekvdefunknownNoVal{\string\evaluation@row}{}
\makeatother
\begin{document}
\Evaluation[cc={n=1,e=2,h=3,j=error}, projet={h=8}]
\end{document}
\keys_set_known:nn
instead of\keys_set:nn
. You could handle second level keys either by setting up a subdirectory in the key tree and using the.meta:nn
handler, or by using.code:n
and nesting a\keys_set_known:nn
inside that.code:n
(roughly the same), or parse the nested list inside of.code:n
with one of\prop_set_from_keyval:Nn
or\keyval_parse:nnn
._tl
in their name, so it should be\l__evaluation_cc_tl
for example.projet
?