6

I am trying to programme a command in x parse that has one optional argument, but which can behave in three ways in the following situations: a) no argument specified, b) optional argument specifies a specific value (p), c) optional argument specifies a different value (q).

The commands would look as follows:

\command

\command[p]

\command[q]

and would give the result

command

command preface

command q

I have tried to use the star and token arguments instead of the standard optional argument but the documentation is very sparse for the package and I cannot work out, even from looking at examples on this site, how I might achieve the above.

My attempt was as follows:

\documentclass{article}
\usepackage{xparse}

\NewDocumentCommand \command { tp } {%
    \IfNoValueTF{#1}{%
    command}%
    {{\IfBooleanTF{#1}%
    {command preface}%
    {command #1}%
    }}}

\begin{document}

\command
\command[p]
\command[10]

\end{document}
8
  • –1: Questions only asking “do it for me” or the like are not really welcome here. Please add a MWE showing your own efforts and I’ll be happy to take my downvote back ;-)
    – Tobi
    Commented Nov 26, 2013 at 11:14
  • xparse is meant to grab arguments: further processing of the content is left to 'other code'. What have you tried so far?
    – Joseph Wright
    Commented Nov 26, 2013 at 11:16
  • Tobi: I thought I might get that response, but I genuinely tried and my efforts were so far from working that I didn't see much point in posting them. Truth is, I didn't really know where to start with the problem. I would have been happy with a response like "here is a site that explains xparse in more detail than the documentation" rather than an actual solution, as I could not find such a resource.
    – DavidR
    Commented Nov 26, 2013 at 11:34
  • @DavidRowthorn: Hm … showing some code even if it don’t work will help. I don’t like questions that have the “just do it for me” attitude – and your’s looks that way ;-) But as you can see in the fact that I provided an answer I’m not that upset ;-) and I redeem my downvote. (ps. Note that you need an @ in front of a name to get the user notified …)
    – Tobi
    Commented Nov 26, 2013 at 12:06
  • 1
    Since your interface doens’t make sense to me I can hardly tell how to improve your attempt, but see what I added to my answer.
    – Tobi
    Commented Nov 26, 2013 at 12:18

2 Answers 2

5

You don’t need xparse in that case. You can do a case switch with the xstring package:

\documentclass{article}

\usepackage{xstring}

% with xstring
\newcommand{\mycmd}[1][-no-value-]{%
   command does
   \IfStrEqCase{#1}{%
      {-no-value-}{no value}%
      {p}{preface}%
   }[#1 value]
   stuff
}

% a more clever version (see comments) with xparse
\usepackage{xparse}
\NewDocumentCommand{\myothercmd}{ o }{%
   command does
   \IfNoValueTF{#1}{no value}{%
      \IfStrEq{#1}{p}{preface}{#1}%
   }
   stuff
}

\begin{document}
\mycmd

\mycmd[p]

\mycmd[q]

\mycmd[-no-value-] is a 'wrong' argument and confuses the code.
So it should be something where you are sure that it won't be the
argument of \verb+\mycmd+

\bigskip
\myothercmd

\myothercmd[p]

\myothercmd[q]

\mycmd[-NoValue-] \texttt{xparse} know how to handle this.
\end{document}

Trying to correct your attempt gives

\NewDocumentCommand \yourcmd { t{+} o } {%
   \IfBooleanTF{#1}{command preface}{%
      \IfNoValueTF{#2}{%
         command%
      }{%
         command #2%
      }%
   }%
}

As you can see the p argument take an argument specifying the <token> that should be tested this toke cant be a letter, e.g. p, because \yourcmdp will be another command in TeX’s eyes and not \yourcmd followed by token p. The corrected version can be used as

\yourcmd
\yourcmd+
\yourcmd[q]
\yourcmd+[q]

giving

command
command preface
command q
command preface

5
  • Note that xparse's -NoValue- is not returned if you do \mycmd[-NoValue-], i.e (without significant effort) you can't 'confuse' the code with the 'wrong' optional argument.
    – Joseph Wright
    Commented Nov 26, 2013 at 11:15
  • So you mean, that I should prefer the xparse way instead my own -no-value- approach?
    – Tobi
    Commented Nov 26, 2013 at 11:16
  • Depends on the use case: usually you don't need to worry about users entering 'difficult' values, but it is at least worth being aware of.
    – Joseph Wright
    Commented Nov 26, 2013 at 11:17
  • I was aware of the fact that my approach is confusable in that way but I wasn’t aware of the fact that xparse is more clever. Thanks!
    – Tobi
    Commented Nov 26, 2013 at 11:24
  • I was not aware of the xstring package, but it is exactly what I needed. thanks
    – DavidR
    Commented Nov 26, 2013 at 13:43
3

xparse doesn't provide helpers for this situation, so going deeper with comparing strings is necessary.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\command}{o}
 {
  \IfNoValueTF{#1}
   {
    <No optional value code>
   }
   {
    \rowthorn_check_argument:n { #1 }
   }
 }

\cs_new:Npn \rowthorn_check_argument:n #1
 {
  \str_case:nnF { #1 }
   {
    {p}{ \rowthorn_command:n { Preface } }
   }
   { \rowthorn_command:n { #1 } }
 }

\cs_new_protected:Npn \rowthorn_command:n #1
 {
  <do something with #1>
 }
\ExplSyntaxOff

\begin{document}

\command

\command[p]

\command[Introduction]

\end{document}

I don't think this is a good interface, though.

You must log in to answer this question.

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