0

I'm encountering some rather unusual behavior from a macro I've defined. The specific goal of this macro, ultimately, is to set up something easy to call that produces itemized lists to my liking without indentation hell. I've omitted the itemization code since it doesn't affect this behavior. The MWE code, with my comments, is as follows.

\documentclass{article}

\makeatletter
  \newcommand{\startfoo}{             % Macro Entry
    \@ifnextchar\foo                  %
      { START FOO \\ \@nextfoo }      % nextchar == \foo, start FOO section
      { } }                           % nextchar != \foo
  \newcommand\@nextfoo[2]{ #2 \\      % Display a foo. #1 is \foo
    \@ifnextchar\bar                  %
      { START BAR \\ \@nextbar }      % nextchar == \bar, start BAR section
      { \@checkfoo } }                % nextchar != \bar
  \newcommand\@nextbar[2]{ #2 \\      % Display a bar. #1 is \bar
    \@ifnextchar\zot                  %
      { START ZOT \\ \@nextzot }      % nextchar == \zot, start ZOT section
      { \@checkbar } }                % nextchar != \zot
  \newcommand\@nextzot[2]{ #2 \\      % Display a zot, #1 is \zot
    \@checkzot }                      %
  \newcommand\@checkzot{              % Check if nextchar is \zot
    \@ifnextchar\zot                  %
      { \@nextzot }                   % nextchar == \zot, continue section
      { \@endzot } }                  % nextchar != \zot
  \newcommand\@checkbar{              % Check if nextchar is \bar
    \@ifnextchar\bar                  %
      { \@nextbar }                   % nextchar == \bar, continue section
      { \@endbar } }                  % nextchar != \bar
  \newcommand\@checkfoo{              % Check if nextchar is \foo
    \@ifnextchar\foo                  %
      { \@nextfoo }                   % nextchar == \foo, continue section
      { \@endfoo } }                  % nextchar != \foo
  \newcommand\@endzot{ END ZOT \\     % End ZOT section
    \@checkbar}                       % Go check on BAR
  \newcommand\@endbar{ END BAR \\     % End BAR section
    \@checkfoo}                       % Go check on FOO
  \newcommand\@endfoo{ END FOO \\  }  % End FOO section, We're done
\makeatother

\begin{document}  % Expected Output:  | Actual Output:
  \startfoo       %
  \foo{foo1}      % START FOO         | START FOO
                  % foo1              | foo1
    \bar{bar1}    % START BAR         | START BAR
                  % bar1              | bar1
      \zot{zot1}  % START ZOT         | START ZOT
                  % zot1              | zota
      \zot{zota}  % zota              | zota
                  % END ZOT
                  % END BAR
  \foo{foo2}      % foo2              | foo2
                  % END FOO           | END ZOT
                  %                   | END BAR
                  %                   | END FOO
  THUD            % THUD              | THUD
\end{document}    %

What 'appears' to be happening, to me, is \@ifnextchar is comparing \zort and the second \foo and evaluating to true, and thus interpreting the \foo line as though it were a \zort.

\@nextzort and \@nextbar seem functionally identical, but if I comment out all lines containing zort so it's just foo and bar, the macro seems to work perfectly.

I'm obviously missing something here, but I need help finding out what that is. Have I gone down a wrong path all together?

1

The coding is somewhat strange but the main error is that \@ifnextchar is an \ifx test so all undefined commands test equal. If you define \foo, \bar and \zot to anything distinct then you get the behaviour you expected.

\documentclass{article}
\let\foo=F
\let\bar=B
\let\zot=Z

\makeatletter
  \newcommand{\startfoo}{             % Macro Entry
    \@ifnextchar\foo                  %
      { START FOO \\ \@nextfoo }      % nextchar == \foo, start FOO section
      { } }                           % nextchar != \foo
  \newcommand\@nextfoo[2]{ #2 \\      % Display a foo. #1 is \foo
    \@ifnextchar\bar                  %
      { START BAR \\ \@nextbar }      % nextchar == \bar, start BAR section
      { \@checkfoo } }                % nextchar != \bar
  \newcommand\@nextbar[2]{ #2 \\      % Display a bar. #1 is \bar
    \@ifnextchar\zot                  %
      { START ZOT \\ \@nextzot }      % nextchar == \zot, start ZOT section
      { \@checkbar } }                % nextchar != \zot
  \newcommand\@nextzot[2]{ #2 \\      % Display a zot, #1 is \zot
    \@checkzot }                      %
  \newcommand\@checkzot{              % Check if nextchar is \zot
    \@ifnextchar\zot                  %
      { \@nextzot }                   % nextchar == \zot, continue section
      { \@endzot } }                  % nextchar != \zot
  \newcommand\@checkbar{              % Check if nextchar is \bar
    \@ifnextchar\bar                  %
      { \@nextbar }                   % nextchar == \bar, continue section
      { \@endbar } }                  % nextchar != \bar
  \newcommand\@checkfoo{              % Check if nextchar is \foo
    \@ifnextchar\foo                  %
      { \@nextfoo }                   % nextchar == \foo, continue section
      { \@endfoo } }                  % nextchar != \foo
  \newcommand\@endzot{ END ZOT \\     % End ZOT section
    \@checkbar}                       % Go check on BAR
  \newcommand\@endbar{ END BAR \\     % End BAR section
    \@checkfoo}                       % Go check on FOO
  \newcommand\@endfoo{ END FOO \\  }  % End FOO section, We're done
\makeatother

\begin{document}  % Expected Output:  | Actual Output:

  \startfoo       %
  \foo{foo1}      % START FOO         | START FOO
                  % foo1              | foo1
    \bar{bar1}    % START BAR         | START BAR
                  % bar1              | bar1
      \zot{zot1}  % START ZOT         | START ZOT
                  % zot1              | zota
      \zot{zota}  % zota              | zota
                  % END ZOT
                  % END BAR
  \foo{foo2}      % foo2              | foo2
                  % END FOO           | END ZOT
                  %                   | END BAR
                  %                   | END FOO
  THUD            % THUD              | THUD

\end{document}    %

It would be far simpler to define \foo, \bar and \zot to give whatever layout you need rather than make each command look ahead in this way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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