For a simple task, imho1, nothing beats the simplicity of expkv-cs and \ekvcSplit (this only works for up to 9 keys, for more it's most likely better to use methods from expkv-def which work similar to \DeclareKeys -- or another key=value implementation like the one built into LaTeX).
1I'm the author of expkv and family.
To have an easy way to add formatting instructions and extra text to a key one can use a front facing key that decorates some internal key. So every time you say link = www.example.com this becomes link-internal={ (See www.example.com)}.
Also in expkv you don't have to hide an additional =, but you'd have to hide a ,.
This borrows the example created by @campa and modifies it to use expkv-cs:
\documentclass{article}
\usepackage{expkv-cs}
\ekvcSplit\task
{
% set up primary keys, all defaulting to an empty value
definition = {}
,source-internal = {}
,link-internal = {}
}
{This is a task with definition #1.#2#3}
% set up decorators
\ekvcSecondaryKeys\task
{
meta source = {source-internal = { You can find its source in #1.}}
,meta link = {link-internal = { (See #1)}}
}
\begin{document}
\parindent0pt
\task{definition=$x=3$}\par
\task{definition=$x=3$, source=ABC}\par
\task{definition=$x=3$, link=https://youtube.ru}\par
\task{definition=$x=3$, source=ABC, link=https://youtube.ru}
\task{definition=$x=3$}
\end{document}
Alternatively to the \ekvcSplit version, you could also use the \ekvcHash version, in which you can access the key-values by name (the entire list will be forwarded inside of #1, and \ekvcValue can be used to access items from that list -- this works for arbitrary many keys).
\documentclass{article}
\usepackage{expkv-cs}
\ekvcHash\task
{
% set up primary keys, all defaulting to an empty value
definition = {}
,source-internal = {}
,link-internal = {}
}
{%
This is a task with definition \ekvcValue{definition}{#1}.%
\ekvcValue{source-internal}{#1}%
\ekvcValue{link-internal}{#1}%
}
% set up decorators
\ekvcSecondaryKeys\task
{
meta source = {source-internal = { You can find its source in #1.}}
,meta link = {link-internal = { (See #1)}}
}
\begin{document}
\parindent0pt
\task{definition=$x=3$}\par
\task{definition=$x=3$, source=ABC}\par
\task{definition=$x=3$, link=https://youtube.ru}\par
\task{definition=$x=3$, source=ABC, link=https://youtube.ru}
\task{definition=$x=3$}
\end{document}
If you want an interface closer to the one provided by \DeclareKeys you could use expkv-def. In addition to a store-handler it also provides dataT. The instruction dataT link = \taskLink will define \taskLink such that by default it'll gobble the next token or brace-group, but if the key was used it'll put the value as {<value>} behind the next token or brace-group (and would strip the braces from that following brace-group).
\documentclass{article}
\usepackage{expkv-def}
\ekvdefinekeys{task}
{
store definition = \taskDefinition
,dataT source = \taskSource
,dataT link = \taskLink
}
\newcommand\taskSourceFormatter[1]{ You can find its source in #1.}
\newcommand\taskLinkFormatter[1]{ (See #1)}
\newcommand\task[1]
{%
\begingroup
\ekvset{task}{#1}%
This is a task with definition \taskDefinition.%
\taskSource\taskSourceFormatter
\taskLink\taskLinkFormatter
\endgroup
}
\begin{document}
\parindent0pt
\task{definition=$x=3$}\par
\task{definition=$x=3$, source=ABC}\par
\task{definition=$x=3$, link=https://youtube.ru}\par
\task{definition=$x=3$, source=ABC, link=https://youtube.ru}
\task{definition=$x=3$}
\end{document}
And if you really want to, you could use basically the same syntax as for keyval by using the basic expkv without any of the extension packages:
\documentclass{article}
\usepackage{expkv}
\newcommand\taskDefinition{}
\newcommand\taskSource{}
\newcommand*\taskLink{}
\ekvdef{task}{definition}{\def\taskDefinition{#1}}
\ekvdef{task}{source}{\def\taskSource{#1}}
\ekvdef{task}{link}{\def\taskLink{#1}}
\newcommand\task[1]
{%
\begingroup
\ekvset{task}{#1}%
This is a task with definition \taskDefinition.%
\ifx\taskSource\empty\else\space You can find its source in \taskSource.\fi
\ifx\taskLink\empty\else\space (See \taskLink)\fi
\endgroup
}
\begin{document}
\parindent0pt
\task{definition=$x=3$}\par
\task{definition=$x=3$, source=ABC}\par
\task{definition=$x=3$, link=https://youtube.ru}\par
\task{definition=$x=3$, source=ABC, link=https://youtube.ru}
\task{definition=$x=3$}
\end{document}
Result of all code blocks:

\newcommand, you may want to provide default values. See e.g. here: https://en.wikibooks.org/wiki/LaTeX/Macros#New_commands . // Hint: you may also find the column to the right helpful (Linked, Related) – MS-SPO Aug 16 '23 at 06:49keyvalhas backwards compatibility with older LaTeX in its favour. – cfr Aug 16 '23 at 13:02keyval. I certainly didn’t intend for you to delete the answer. – Gaussler Aug 16 '23 at 13:22;-)) – campa Aug 16 '23 at 15:44