# Mix value and key/value with xparse

Following an earlier question I switched to xparse. Now I am sitting in a compatibility trap and try to allow old and new stuff at the same time. The point of origin is the infamous macro with two optional arguments. My minimal example is:

\documentclass{minimal}

\usepackage{xparse}

\NewDocumentCommand \sidenotetext { o o m } {%
(#1), (#2), #3
}%

\begin{document}
\sidenotetext{arg} % case (1)

\sidenotetext[1]{arg} % \sidenotetext[mark=1]{arg}; case 2

\sidenotetext[][]{arg} % case 3

\sidenotetext[][2]{arg} %\sidenotetext[offset=2]{arg}; case 4

\sidenotetext[3][]{arg} %\sidenotetext[mark=3]{arg}; case 5

\sidenotetext[4][5]{arg} %\sidenotetext[mark=4,offset=5]{arg}; case 6
\end{document}


Is it possible to make the left and the right macros (commented out) work at the same time? If not, Is it possible at all to make case 2 work, i.e. no key always means mark and the rest is key value? I assume, l3keys is the right choice to play nice with xparse?

If the two optional arguments deal with incompatible types of argument, the only feasible way is to have one before and one after the mandatory argument, so

\NewDocumentCommand{\sidenotetext} { o m o }
{%
\IfNoValueTF{#1}...
}


or

\NewDocumentCommand{\sidenotetext} { O{default} m O{default} }
{%
...
}


In this way you can call

\sidenotetext{text}
\sidenotetext[1]{text}
\sidenotetext{text}[2]
\sidenotetext[1]{text}[2]


However this is clumsy. Better going with a key-value approach.

\ExplSyntaxOn
\NewDocumentCommand{\sidenotetext}{ O{} m }
{
\group_begin:
\andy_sidenotetext:nn { #1 } { #2 }
\group_end:
}

\keys_define:nn { andy/sidenote }
{
mark .tl_set:N = \l_andy_sidenote_mark_tl,
offset .tl_set:N = \l_andy_sidenote_offset_tl,
offset .initial = 0,
}

\cs_new_protected:Npn \andy_sidenotetext:nn #1 #2
{
\keys_set:nn { andy/sidenote } { #1 }
<code using \l_andy_sidenote_mark_tl, \l_andy_sidenote_offset_tl
and #2 (the actual text)>
}
\ExplSyntaxOff


Making the two calls compatible with each other is something I wouldn't recommend: stick to one syntax. There are macros around that allow both approaches, but it's because they were defined when a key-value approach was unfeasible. An example is \section in Koma-Script classes, where the test for a key-value syntax is done on the basis whether a = appears in the optional argument, which is not very robust.

If what you want to do is redefining a legacy command, I would recommend using a different name.