3

I sometimes define an argument processor to (imho) simplify some code if I want to write a wrapper around another macro. For example if I write a wrapper around a macro that takes an optional * I could end up using a number of branching tests in the form of \IfBooleanTF{#1}{...}{...}, but I think it is convenient to do something like the following sometimes:

\newcommand\sProc[1]
  {%
    \IfBooleanTF{#1}
      {\def\ProcessedArgument{*}}
      {\def\ProcessedArgument{}}%
  }
\NewDocumentCommand \wrapchap { >{\sProc}s m }
  {%
    \chapter#1{#2}%
  }

For s-type arguments this works quite well. However for o-type arguments this doesn't work as shown by the following MWE

\documentclass[]{article}

\usepackage{xparse}
\newcommand\oProc[1]
  {%
    \IfValueTF{#1}
      {\def\ProcessedArgument{[#1]}}
      {\def\ProcessedArgument{}}%
  }
\NewDocumentCommand \foo { >{\oProc}o m }
  {%
    \bar#1{#2}%
  }
\renewcommand\bar[2][default]
  {%
    \begin{tabular}{ll}
      optional  & #1  \\
      mandatory & #2 \\
    \end{tabular}\\
  }
\NewDocumentCommand \FOO { o m }
  {%
    \IfValueTF{#1}
      {\bar[#1]{#2}}
      {\bar{#2}}%
  }

\begin{document}
\section{Result}
\foo{baz}
\foo[baz]{bang}

\section{Expectation}
\FOO{baz}
\FOO[baz]{bang}
\end{document}

It works with O-type arguments, which I use in cases like this (a recent example would be this answer).

Questions:

  • How can I make this work, if possible?
  • Why the decision to not apply processors to -NoValue- by default?

EDIT: As pointed out by @egreg this is documented behaviour of xparse. I'm well aware of this, but wonder why this design choice was made. As a result the second of the above questions is the one more interesting to me. I don't really know if the answer to the first question would break things (as I don't know if there is any current code relying on that behaviour).

1

From the documentation of xparse:

0.9 Argument processors
xparse introduces the idea of an argument processor, which is applied to an argument after it has been grabbed by the underlying system but before it is passed to ⟨code⟩. An argument processor can therefore be used to regularise input at an early stage, allowing the internal functions to be completely independent of input form. Processors are applied to user input and to default values for optional arguments, but not to the special -NoValue- marker.

  • I've read this part, but sadly this doesn't answer one of my two questions (how to do it anyway, and why is this not done). I admit that the latter is most likely only answerable by members of the l3-team. – Skillmon Jun 12 '18 at 23:50
  • @Skillmon A better question would be: can you give a real example of use? – egreg Jun 13 '18 at 6:48
  • If I want to be able to recognize whether the optional argument is given at all or just with an empty argument. This can make a difference (e.g. if you write a wrapper around \caption, \wrapcap[]{foo} is not the same as \wrapcap{foo}) and don't want to include the several branches in the macro's definition. Another usage example would be tex.stackexchange.com/a/410816/117050 in which there is a bug (as I just realised) caused by the fact that -NoValue- is not processed. – Skillmon Jun 13 '18 at 7:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.