6

Using \def I can define a command as follows:

\def\aecmd#1 located at (#2);{---definition---}

I can recreate this with xparse as follows:

\NewDocumentCommand\aecmd{ u{~located~at~(}u{);}}{----definition---}

However, I have a situation where I want to be able to write a command with an (almost final) optional argument. This would be a pain in the neck to do with \def.

I'd like a command which could be expressed as either

\aecmd{Manditory content}[optional content] located at (location);

or

\aecmd{Manditory content} located at (location);

Essentially, I would like something that works like r but instead of taking a single token as the delimiters can take whole strings. Let's call this hypothetical argument specifier b

Then my desired command could be defined along these lines:

\NewDocumentCommand{ mob{~located~at~(}{);}{ ---something--- }

I'm aware I could write something like that following:

\NewDocumentCommand\aecmd{ mou{~located~at~(}u{);}{---definition---}

Further, I suppose that I could test whether or not something was passed in the 3rd argument and raise an error if there was anything there.
But this just seems clunky. It doesn't feel right to me.

Any suggestions about how to do this better?

2 Answers 2

6

xparse? Pshaw!

EDITED to capture syntax error if optional argument is unbracketed.

\documentclass{article}
\usepackage{parskip}

\newcommand\aecmd[1]{\def\mandatory{#1}\aecmdaux}
\def\aecmdaux#1 located at (#2);{\def\location{#2}\aecmdauxA{#1}}
\newcommand\aecmdauxA[1]{\setbox0=\hbox{%
  \if[#1[\gdef\next{\aecmdauxB#1}\else \gdef\next{syntax error}\fi}%
  \next%
}
\newcommand\aecmdauxB[1][]{%
  Optional: #1\\ Mandatory: \mandatory\\ location: \location}

\begin{document}
\aecmd{Colonel Mustard} located at (the library);

\aecmd{Colonel Mustard}[with a wrench] located at (the library);

\aecmd{Colonel Mustard} on 4th street located at (the library);
\end{document}

enter image description here

If one does not like the output of "syntax error" then in the definition of \aecmdauxA, the words "syntax error" can be replaced with \aecmdauxB and the effect will be to ignore the stray words in the syntax, while still producing the mandatory and location arguments.

6
  • +1 This is clever. I like it. But, it allows the user to do somehting like \aecmd{Colonel Mustard} on 4th street located at (the library); and might not notice that this is creating spurious output.
    – A.Ellett
    Aug 30, 2018 at 19:17
  • @A.Ellett I designed it based on your two specified input syntax variations provided in the question. What you just gave in the above comment does not fit that form...how should such a thing be digested? Are you implying that optional content should not be specified in brackets? Aug 30, 2018 at 19:24
  • What I'm saying is if something is passed as a 2nd argument that's not in square brackets, then the syntax should be wrong. Anyhow, I do like your solution. It just doesn't catch an input error if the 2nd argument isn't in square brackets.
    – A.Ellett
    Aug 30, 2018 at 19:27
  • @A.Ellett So, to be clear, the 2nd argument should be in brackets, but if it is not, you would like an error generated? Or do you want all the non bracketed content to be taken as the optional argument? I can do that pretty easy. Aug 30, 2018 at 19:29
  • I wouldn't like using nonbracketed content as the optional argument. But, if you've got more tricks that I'm unaware of about generating an error: do by all means share.
    – A.Ellett
    Aug 30, 2018 at 19:32
5

With xparse, but I find such syntax a very bad idea, notwithstanding TikZ using it.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\aecmd}{mou{located~at~(}u{);}}
 {
  \tl_if_blank:nF { #3 } { \ERROR }
  \noindent
  #1~(mandatory)\\
  \IfValueT{#2}{#2~(optional)\\}
  #4~(final)
 }
\ExplSyntaxOff

\begin{document}

\aecmd{Mandatory content}[optional content] located at (location);

\aecmd{Mandatory content} located at (location);

\aecmd{Colonel Mustard} on 4th street located at (the library);

\end{document}

enter image description here

Note that the third call raises an error.

2
  • Actually, TikZ is the reason for me using this sort of syntax. So you're solution is basically the same as my wonky approach. Though I hadn't thought of testing for non-blank.
    – A.Ellett
    Aug 30, 2018 at 20:23
  • @A.Ellett xparse is not the best for this. See how TikZ does, instead.
    – egreg
    Aug 30, 2018 at 20:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .