How can I capture both superscripts and subscripts after a macro

This question piggy-backs on the answer to Capture a macro's subscripts/superscripts by the macro by egreg.

I'm attempting to use the xparse package to create some macros and I'd rather not have to use different macros when I want to have sub and superscripts (or both at once!).

I'd like a macro like this:

\F
\F{m}
\F{m}_b
\F{m}^a
\F{m}_b^a
\F{m}^a_b


to produce output equivalent to this:

$F$
$F[m]$
$F_b[m]$
$F^a[m]$
$F_b^a[m]$
$F^a_b[m]$


Based on the abolve linked question, I can capture one or the other, but not both. I've made a few attempts, but there must be something very fundamental (or subtle) about now @ifnextchar works that is beyond me.

This code takes two optional arguments, rather than one, but the issue remains: The sub and superscripts always end up at the end of the line, not on the defined first character.

\documentclass{article}
\usepackage{xparse}
\makeatletter
\newcommand{\DFcmd}{\ensuremath{F}}

\NewDocumentCommand\DFhelp{ g g g g }
{
\IfValueT{#3}{ \def\@DFcmdsub{\DFcmd^{#3}} }{ \def\@DFcmdsub{\DFcmd} }
\IfValueT{#4}{ \def\@DFcmdsuper{\@DFcmdsub_{#4}} }{ \def\@DFcmdsuper{\@DFcmdsub} }
\@DFcmdsuper
\IfNoValueF{#1}{#1}{}
\IfNoValueF{#2}{#2}{}
}

\NewDocumentCommand\DF{ o o }
{%
\def\firstarg{}%
\def\secondarg{}%
\IfNoValueF{#1}{ \def\firstarg{[#1]} }{ \def\firstarg{} }%
\IfNoValueF{#2}{ \def\secondarg{#2} }{ \def\secondarg{} }%
\def\superopt{}%
\def\subopt{}%
\@ifnextchar^%
{%
\assign@superopt%
\@ifnextchar_%
{%
\assign@subopt%
}%
{%
\def\subopt{}%
}%
}%
{%
\@ifnextchar_%
{%
\assign@subopt%
\@ifnextchar^%
{%
\assign@superopt%
}%
{%
\def\superopt{}%
}%
}
{%
\def\subopt{}%
}%
}
\DFhelp{\firstarg}{\secondarg}{\superopt}{\subopt}%
}

\def\assign@superopt^#1{ \def\superopt{#1} }
\def\assign@subopt_#1{ \def\subopt{#1} }
\makeatother

-
I guess, there are multiple problems in your code: You use \If*ValueT or \If*ValueF but use both branches. Then you specify two optional arguments for \DF which are enclosed in [ and ], but you never use them. \@ifnextchar finds only \bgroup from the {m} argument. Furthermore, you use \assign@superopt right before \@ifnextchar although it expects a ^, this won’t work! Use the next \@ifnextchar inside the definition of \assign@*opt (after it has grabbed its argument). – Qrrbrbirlbel Jun 10 '13 at 19:42
I can't see what gain there is over typing more naturally $F_a^b[m]$. Or, if you don't want to have an explicit "F", $\DF_a^b[m]$, after defining \DF to do what you desire. – egreg Jun 10 '13 at 19:56
This is just a general thing. The idea is that notation (both of the operator and its arguments) isn't 100% set and I was asked if it would be possible to have this behavior in a macro. After spending some time on it, it became an "is it even possible" thing, well beyond the practicality. Now that I have a more clear picture, I'll try and clean the question up some to make it more clear. – renstar Jun 10 '13 at 20:02

The following grabs multiple sub and superscripts.

The argument in braces (which apparently is optional) should probably better be in [ ].

Code

\documentclass{article}
\makeatletter
\def\F{%
\let\f@sub\@empty
\let\f@super\@empty
\let\f@main\@empty
\@ifnextchar\bgroup\f@catch@main\f@test
}
\def\f@catch@main#1{\def\f@main{#1}\f@test}
\def\f@test{%
\@ifnextchar_\f@catch@sub{\@ifnextchar^\f@catch@super\f@finalize}%
}
\def\f@catch@sub_#1{\expandafter\def\expandafter\f@sub\expandafter{\f@sub#1}\f@test}
\def\f@catch@super^#1{\expandafter\def\expandafter\f@super\expandafter{\f@super#1}\f@test}
\def\f@finalize{%
F
\ifx\f@sub\@empty\else_{\f@sub}\fi
\ifx\f@super\@empty\else^{\f@super}\fi
\ifx\f@main\@empty\else[\f@main]\fi
}
\makeatother
\begin{document}
$\F$ \par
$\F{m}$ \par
$\F{m}_b$ \par
$\F{m}^a$ \par
$\F{m}_b^a$ \par
$\F{m}^a_b$ \par
$\F{m}^a_b_a^b$ \par
\end{document}


Output

-
+1 (because you beat me by 28 seconds:-) and this implements what the OP asked for (making a {} delimited argument optional) but as I note in my answer this goes against LaTeX syntax either the argument should be mandatory or should be [] delimited. – David Carlisle Jun 10 '13 at 19:38
I ended up using something based on this answer to get the desired effect. I think the others would have worked as well, but something very similar to this did the trick. Thanks everyone! – renstar Jun 12 '13 at 14:14

Since you only have one mandatory argument (and you are looking for ^ and _) I don't think xparse gains you a lot so i just use \@ifnextchar directly here. Also because you have m in a mandatory {} argument it should always be given so I changed \F to \F{} and added a test for the argument to be empty. (An alternative would be to make the argument optional but then it should be delimited by [] not {}.

\documentclass{article}

\makeatletter
\def\F#1{\def\F@{\ifx\relax#1\relax\else[#1]\fi}\def\F@@{F}\@ifnextchar^\@Fsp\@Fnsp}
\def\@Fsp^#1{\def\F@@{F^{#1}}\@ifnextchar_\@Fspsb{\F@@\F@}}
\def\@Fspsb_#1{\F@@_{#1}\F@}
\def\@Fnsp{\@ifnextchar_{\@Fsb}{\F@@\F@}}
\def\@Fsb_#1{\def\F@@{F_{#1}}\@ifnextchar^\@Fsbsp{\F@@\F@}}
\def\@Fsbsp^#1{\F@@^{#1}\F@}
\begin{document}

$\F{}$

$\F{m}$

$\F{m}_b$

$\F{m}^a$

$\F{m}_b^a$

$\F{m}^a_b$

\end{document}

-
I actually have no mandatory arguments, just a few optional ones. I tried to scrub things from my example that had nothing to do with (what I thought) was causing issues. xparse allows both [] and {} to be optional via 'o' and 'g' arguments. – renstar Jun 10 '13 at 19:42
@renstar perhaps, but you shouldn't use optional {} arguments in latex2e:-) – David Carlisle Jun 10 '13 at 19:44
Fair enough, I can (and probably will) go with that, but then, why does xparse provide that as an option? – renstar Jun 10 '13 at 19:53
@renstar maybe the rules will be different in latex3 (we haven't written the rules yet... – David Carlisle Jun 10 '13 at 19:56

The following seems to work reasonably well with (at least) the limitation that it requires a space after the macro in order to work.

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn

\NewDocumentCommand{\F}{}{
\peek_charcode:NTF \c_group_begin_token
{\renstar_F:w}
{$F$}
}

\cs_new:Npn \renstar_F:w #1#2~ {
\ensuremath{F#2[#1]}~
}

\ExplSyntaxOff

\begin{document}

\F

\F{m}

\F{m}_b

\F{m}^a

\F{m}_b^a

\F{m}^a_b

\end{document}

-

I'd go into a completely different direction. In your case there is no gain whatsoever in defining a complicated macro rather than typing more naturally

$F_{a}^{b}[m]$


In case this is only an example of a more complex situation, I would recommend you a key-value syntax, that avoids chasing for tokens and distinguishing among different situations. This is also more flexible.

Here's the example.

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\DF}{O{}}
{
\group_begin:
\keys_set:nn { renstar/DF } { #1 }
\renstar_DF:
\group_end:
}
\keys_define:nn { renstar/DF }
{
arg .tl_set:N = \l_renstar_arg_tl,
sub .tl_set:N = \l_renstar_sub_tl,
sup .tl_set:N = \l_renstar_sup_tl,
symbol .tl_set:N = \l_renstar_symbol_tl,
symbol .initial:n = F,
}
\cs_new:Npn \renstar_DF:
{
\l_renstar_symbol_tl
\tl_if_empty:NF \l_renstar_sub_tl
{ \c_math_subscript_token { \l_renstar_sub_tl } }
\tl_if_empty:NF \l_renstar_sup_tl
{ \c_math_superscript_token { \l_renstar_sup_tl } }
\tl_if_empty:NF \l_renstar_arg_tl
{ [ \l_renstar_arg_tl ] }
}
\ExplSyntaxOff

\begin{document}
$\DF$

$\DF[arg=m]$

$\DF[arg=m,sub=a]$

$\DF[sup=b,arg=m]$

$\DF[arg=m,sup=b,sub=a]$

$\DF[symbol=M,sup=x,arg=f]$
\end{document}


-