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.

I understand the definitions of the \makeatletter and \makeatother commands and also \def and \newcommand somewhat. But, explained in a simple way, what is happening in the following line?

\@ifnextchar[ \@myitem{\@noitemargtrue\@myitem[\@itemlabel]}}

Of Gonzalo Medina's answer at:

Forcing new line after item number in enumerate environment

share|improve this question
add comment

2 Answers

up vote 32 down vote accepted

\@ifnextchar is a LaTeX conditional that peeks ahead at the following character. So, \@ifnextchar[ looks ahead to see if the following character in the input stream is a [ (opening left bracket). If this is true, then it executes the immediately following token, otherwise, it skips it and executes the token following that.

The first token, executed upon a true evaluation of \@ifnextchar[ is \@myitem. If the evaluation is false, it executes {\@noitemargtrue\@myitem[\@itemlabel]}} - the following group or "token", which also calls \@myitem now with an optional argument set [\@itemlabel]. Before calling \@myitem, the boolean \if@noitemarg is set to true (\@noitemargtrue).

The general idea behind this expression is to condition on whether an optional argument is supplied or not, and therefore avoid an error if you pass arguments to a macro where the parameter text does not match what is given. Using the above example, \@mymacro is defined using

\def\@myitem[#1]{<replacement text>}

Since this uses \def for the definition, the "optional" argument is actually not optional, but required. That's why the above usage is necessary. A more conventional way of conditioning is supplied using

\newcommand{\@myitem}[1][<arg>]{<replacement text>}

where <arg> specifies the value of the optional argument if it is not explicitly specified. xparse provides similar conditioning that, for the upper-level user, might be more intuitive.

share|improve this answer
add comment

This is a very important function in the LaTeX kernel. The macro

\@ifnextchar

takes three argument. The first one should be a single token, usually [ but not necessarily.

When the input stream has the following tokens

\@ifnextchar<token>{<true>}{<false>}

TeX will look at the next token (skipping spaces) and compare it to the <token> which is the first argument to \@ifnextchar and will not remove it from the input stream.

If the two tokens coincide (have the same meaning, to be precise), TeX will use the <true> code, otherwise the <false> code.

The old fashioned way to define commands with an optional and a mandatory argument was something like

\newcommand{\xyz}{\@ifnextchar[{\@xyz}{\@xyz[default]}}
\def\@xyz[#1]#2{do something with #1 and #2}

where default is the default value for the optional argument. Nowadays we'd say

\newcommand\xyz[2][default]{something with #1 and #2}

(which eventually will do the same working as the old fashioned definition, but in a safer way). If the call is

\xyz[a]{b}

the test of \@ifnextchar would be true, so TeX would expand this into

\@xyz[a]{b}

because the [ is not removed as would be an argument. With

\xyz{b}

the test would be false, so the tokens would be replaced by

\@xyz[default]{b}

keeping TeX happy with respect to the definition of \@xyz.


The same applies in your case, with the difference that the <false> text has something more in it:

  1. \@ifnextchar[\@myitem{\@noitemargtrue\@myitem[\@itemlabel]}}[aaa] bbb will become

    \@myitem[aaa] bbb
    
  2. \@ifnextchar[\@myitem{\@noitemargtrue\@myitem[\@itemlabel]}} bbb will become

    \@noitemargtrue\@myitem[\@itemlabel] bbb
    

so supplying a suitable argument between square brackets to \@myitem and setting a conditional.

Since the second argument to \@ifnextchar, in this case, is a single token, it doesn't need braces around it. The code

\@ifnextchar[{\@myitem}{\@noitemargtrue\@myitem[\@itemlabel]}}

would be completely equivalent.


See this answer for an explanation of how \@ifnextchar works internally in terms of \futurelet and this other one for a description of \futurelet (both by Martin Scharrer).

share|improve this answer
5  
:no wonder you are the no. 1, very clear explanations. grazie –  Abhimanyu Arora May 29 '12 at 18:02
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.