# Argument of … has an extra }, recursive macro

Note: This is (unfortunately) not a simple “fix your matching braces” issue, please read the whole question.

I’m working on a command to fix the spacing of \vec — the spacing is too small by default, leading to collisions with the arrow and following glyphs in cases like (\vec p). However, simply redefining the command, as in

\makeatletter
\let\oldvec\vec
\def\vec#1{\oldvec{#1}\@ifnextchar{^}{\kern 1pt}{}}
\makeatother


doesn’t work in cases where the vector has both a superscript and a subscript. Therefore, a command that recursively deals with oncoming super- and subscripts is required.

Currently, I’m using the following solution (optimized for Stix/Times, so may not look great with Computer Modern). However, a subscript containing a single command that takes an argument will fail unless the atom is encased in braces (e.g. \vec a_\textup{max} doesn’t work, \vec a_{\textup{max}} and \vec a_\pi work).

MWE:

\documentclass{article}

\makeatletter
\let\oldvec\vec
\def\vec#1{\oldvec{#1}\vec@}
\def\vec@{%
\@ifnextchar{_}{\vec@sub}{%
\@ifnextchar{^}{\vec@sup}{{\kern 0.5pt}}}%
}%
\def\vec@sub#1#2{_{\kern -0.75pt #2}\vec@}
\def\vec@sup#1#2{^{\kern 2pt #2}\vec@}
\makeatother

\begin{document}
% works
$\vec s_{\textrm{max}}$

% doesn't work
$\vec s_\textrm{max}$
\end{document}


Error code:

! Argument of \textrm  has an extra }.
<inserted text>
\par
l.16 $\vec s_\textrm {max}$


I think it has to do with the \vec@sub and \vec@sup commands ending a group before the argument is given (so that the parser sees {\vec{a}_\textrm}{a} or something and panics) but I’m not entirely sure how to figure that out.

Full disclosure: This code is “adapted” (read: nearly entirely copied from) this answer by @siracusa, and it definitely involves TeX code a little bit higher than my normal skill level. I have read what I could find on \@ifnextchar and so on, but I’m not 100% certain on all the elements playing out here.

Thanks for your help with this oddball problem!

• Off topic: Why not use \max? – Sigur Mar 24 '17 at 2:54
• Both $\vec s_\max$ and $\vec s_{\textrm{max}}$ do not produce errors here. But the second has bigger max font. – Sigur Mar 24 '17 at 2:57
• _{<arg>} is the correct syntax anyway. – cfr Mar 24 '17 at 4:16
• the fact that _\textrm{a} works using a primitive subscript is an unfortunate side effect of the primitive behaviour. It is very hard to support that using macro arguments and is anyway incorrect latex syntax so it is better just do document that it is not supported as do other packages that use macros here eg breqn or tex4ht etc – David Carlisle Mar 24 '17 at 7:52
• @9999years it's not entirely accidental that it works with the primitive _ but it has never been supported latex syntax. the latex book will tell you even to brace a single character x^{2} not x^2 but certainly if _ is a macro _\textrm{zz} is the same as _{\textrm}{zz} and gives an error just as \fbox\textrm{zz} is \fbox{\textrm}{zz} and gives the same error. – David Carlisle Mar 24 '17 at 18:28

The fact that _\textrm{a} works using a primitive subscript is an unfortunate side effect of the primitive behaviour. It is very hard to support that using macro arguments and is anyway incorrect latex syntax so it is better just do document that it is not supported as do other packages that use macros here eg breqn or tex4ht etc.
The fact that it works depends on _ being a tex primitive not a macro, and on the internal details of \textrm and similar commands (that expand to a single brace group). The outwardly similar construct x_\fbox{a} does not work for example and requires x_{\fbox{a}}.
If _ is made into a macro then it (most likely) loses this ability to find braces hidden inside macros. If instead of _ you use \fbox\textrm{x} then you get essentially the same error as you shown because \fbox gets just \textrm as argument. The correct markup is \fbox{\textrm{a}}