Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

How can you define a macro \cmd in TeX primitives using two optional arguments (and a mandatory one) that fulfills the property that calling \cmd[opt]{mand} is equivalent to \cmd[][opt]{mand}. Yet, I only managed to create this macro with beeing \cmd[opt]{mand} an equivalent call to \cmd[opt][]{mand}. I don't really get which kind of questions I have to propose to TeX in order to achieve what I have in mind. Do you have any suggestions?

share|improve this question
1  
Welcome to TeX.sx! A tip: You can use backticks ` to mark your inline code as I did in my edit. Why don't you post the code you have produced so far? –  Jubobs Apr 24 '13 at 22:50
3  
I'm confused: you tagged the question with {plain-tex} but also with {etoolbox} which is a LaTeX package: do you want a plain TeX solution or are LaTeX macros or even etoolbox' macros allowed? –  cgnieder Apr 24 '13 at 22:57
    
Have you seen More than one optional argument for newcommand? –  doncherry Apr 24 '13 at 23:00
    
Ok. I understand your point. An explanation: I am looking for a Plain TeX solution in the first place, but one can never know (especially when someone does not have deep insights into the system, like me) if there is another solution. As far as etoolbox provides a bunch of if conditionals, i thaught that there could be a way to solve the problem in LaTeX style. –  Ruben Apr 25 '13 at 7:55
    
@Ruben There are a few subtleties in optional arguments; for instance, in my answer I made no attempt at eating possible white space between the optional arguments. Moreover you should specify whether you want to use defaults for unexpressed optional arguments (this would be easily accommodated). –  egreg Apr 25 '13 at 13:17

4 Answers 4

up vote 6 down vote accepted

Here's a way, although it's not clear what you really would like to achieve.

\long\def\firstoftwo#1#2{#1}
\long\def\secondoftwo#1#2{#2}

\def\cmd{\futurelet\next\cmdi}
\def\cmdi{%
  \ifx\next[%
    \expandafter\firstoftwo
  \else
    \expandafter\secondoftwo
  \fi
  {\cmdopt}%
  {\cmdx[][]}%
}
\def\cmdopt[#1]{\def\firstopt{#1}%
  \futurelet\next\cmdoptii}
\def\cmdoptii{%
  \ifx\next[%
    \expandafter\firstoftwo
  \else
    \expandafter\secondoftwo
  \fi
  {\expandafter\cmdx\expandafter[\firstopt]}%
  {\expandafter\cmdx\expandafter[\expandafter]\expandafter[\firstopt]}%
}

\def\cmdx[#1][#2]#3{%
  \par\noindent{\tt\string\cmd} called with:\par
  first optional argument=#1;\par
  second optional argument=#2;\par
  mandatory argument=#3\par}

\cmd{abc}
\cmd[opt1]{abc}
\cmd[opt1][opt2]{abc}

\bye

enter image description here

share|improve this answer
    
I think, he wants the second of two in \cmdoptii to be {\expandafter\cmdx\expandafter[\expandafter]\expandafter[\firstopt]}%. –  Qrrbrbirlbel Apr 24 '13 at 23:17
    
@Qrrbrbirlbel Yes, I was fixing it when I saw your comment –  egreg Apr 24 '13 at 23:21

Here is a way to do what I think you desire with the xparse package:

enter image description here

Notes:

  • In actual usage you need to replace the \{ and \} with a { and }. I used the escaped versions in order to generate the output.

Code:

\documentclass{article}
\usepackage{xparse}

\NewDocumentCommand{\MyCommand}{o o m}{%
    \IfNoValueTF{#1}{%
        Command\{#3\}%  No optional parameters specified
    }{%
        % Optional parameters specified.  
        % Now need to check if #2 was provided.
        \IfNoValueTF{#2}{%
            Command[ ][#1]\{#3\}%  #2 NOT provided
        }{%
            Command[#1][#2]\{#3\}% Both #1 and #2 provided.
        }%
    }%
}

\begin{document}
\MyCommand{no optional paramters}

\MyCommand[optional param1]{one optional paramater}

\MyCommand[optional param1][optional param2]{two optional paramaters}
\end{document}
share|improve this answer

Alright, we’ve got the asked answer from egreg, we’ve got two rather confusing LaTeX3/ answers from Peter Grill and Werner; I’ll throw my LaTeX2 solution in the hat, too.

It uses \kernel@ifnextchar.

Code

\documentclass{article}
\makeatletter
% a)
%\newcommand*{\cmd}[1][]{\kernel@ifnextchar[{\cmd@@[{#1}]}{\cmd@@[][{#1}]}}
% or b)
\def\cmd{\kernel@ifnextchar[\cmd@{\cmd@[]}}
\def\cmd@[#1]{\kernel@ifnextchar[{\cmd@@[{#1}]}{\cmd@@[][{#1}]}}
% a) and b)
\def\cmd@@[#1][#2]#3{opt 1 $\to$ \texttt{#1}; opt 2 $\to$ \texttt{#2}; man $\to$ \texttt{#3}\par}
\makeatother
\begin{document}
\cmd{abc} %             -> \cmd@@[][]{abc}
\cmd[opt1]{abc} %       -> \cmd@@[][opt1]{abc}
\cmd[opt1][opt2]{abc} % -> \cmd@@[opt1][opt2]{abc}
\end{document}

Output

enter image description here

share|improve this answer

Here's an answer based on this great answer. Basically, you use two \newcommands with one optional argument each, and have one call the other. There is a bit of a complication in distinguishing when the second one is simply missing or is present but empty; I have stolen (rather clumsily) the LaTeX3 approach of using -NoValue- as the indicator for the former, so that the second and fourth examples below return different results.

\documentclass{article}
\usepackage{etoolbox}

\newcommand*\cmd[1][]{%
  \def\argi{#1}%
  \cmdA
}
% Default stolen from LaTeX3, badly
\newcommand*\cmdA[2][-NoValue-]{%
  \def\argii{#1}%
  \ifdefstring{\argii}{-NoValue-}{%
    \let\argii\argi
    \let\argi\empty
  }{}%
  Arg 1: \argi,
  Arg 2: \argii,
  Mandatory arg: #2%
}

\begin{document}

\cmd{x}

\cmd[a]{x}

\cmd[][a]{x}

\cmd[a][]{x}

\cmd[a][b]{x}

\end{document}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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