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.

Imagine I have two commands defined as

\def\witharg#1{something with #1}
\def\without{something without arg}

and I want to define a new command \mycmd that behaves as \witharg if it's followed by an argument (not necessarily enclosed in braces), and behaves like \without if it is not followed by an argument. In fact, the later case can only be true if \mycmd is followed by the token }. To make things slightly more clear, I want

{\mycmd\token\mycmd}

to expand to something similar to the expansion of

{\witharg{\token}\without}

How can I achieve this?

Note that, in fact, trying to evaluate something like {\witharg} fails with TeX complaining that there is an extra }, i.e. the argument to \witharg is missing.

share|improve this question
    
Are you looking for a solution that is strictly in basic TeX? I.E. is LaTeX allowed? –  Sharpie Aug 3 '10 at 3:18
2  
tex-guts is a really ugly term to use. Can we use tex-only or plain-tex instead? –  Will Robertson Aug 3 '10 at 6:07
    
I was trying, you can re-tag of course :) –  Juan A. Navarro Aug 3 '10 at 7:01
    
@SSharpie, I was looking for a TeX answer, but a LaTeX one would also be welcome –  Juan A. Navarro Aug 3 '10 at 7:02
    
I thought the consensus was tex-core? –  Konrad Rudolph Aug 6 '10 at 9:28
add comment

2 Answers

up vote 18 down vote accepted

Whenever you need to check what comes next after a macro, the primitive to use is generally \futurelet (see TeX by Topic for a good reference). In this case, you'd write something like

\def\mycmd{%
  \futurelet\mytoken\myargparse
}

which will \let the following token to \mytoken and then expand \myargparse. Define \myargparse to be conditional on what \mytoken is, and that's it:

\def\myargparse{%
  \ifx\mytoken\closingbracetoken
    \expandafter\without
  \else
    \expandafter\witharg
  \fi
}
\let\closingbracetoken=}

Finally, check that it works:

\def\witharg#1{something with #1}
\def\without{something without arg}
\def\token{TOK}
{\mycmd\token\mycmd}
share|improve this answer
    
More or less what I was about to write :-) –  Joseph Wright Aug 3 '10 at 6:04
    
You would have written your explanations more clearly :) –  Will Robertson Aug 3 '10 at 6:08
    
Excellent, thanks! I found about \futurelet but somehow I couldn't figure out how to test for } or put all of it together. This works nicely! –  Juan A. Navarro Aug 3 '10 at 7:05
add comment

xparse can test for explicit brace-delimited arguments (or other delimiters, see documentation):

\documentclass{article}
\usepackage{xparse}% http://www.ctan.org/pkg/xparse

\NewDocumentCommand\mycmd{g}{%
\IfValueTF{#1}{(something with #1)}{(something without arg)}%
}

\def\token{TOK}
\begin{document}

\mycmd{Hello}

\mycmd

{\mycmd\token\mycmd}

Blah, \mycmd{Hello}, blah, \mycmd, blah

\end{document}

compiled output

share|improve this answer
    
but in the {\mycmd\token\mycmd} case, I wanted \token to be used as an argument to the first \mycmd. Here it seems that the argument is taken only if enclosed by braces? –  Juan A. Navarro Mar 7 '13 at 20:49
    
@JuanA.Navarro: Correct, This approach requires braces when you want to pass an argument, Will's \futurelet approach requires braces when you do not want to pass an argument. Use whichever you find more natural (for my code, I find the "braces when arg wanted" semantics more natural). –  Dean Serenevy Mar 13 '13 at 18:18
add comment

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.