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.

In this example document, I want to make a math relation called R which gets typeset as R^X, but as a math relation. But I want to maybe be able to subscript it. The macro \myRbad looks okay without the subscript, but with a subscript it looks wrong because the subscript occurs "after" the superscript instead of being underneath it as it should be. The macro \myRgood looks correct in either case. It works by checking whether the next character is _ and if it is, gobbling the _ and delegating to another macro which typesets the subscripted version. I wondered though, whether there's a more straightforward way than this to make LaTeX do what I want.

\documentclass[a4paper]{amsart}

\def\myRbad{\mathrel{R^X}}

\makeatletter
\def\@myRgood@#1{\mathrel{R^X_{#1}}}
\def\myRgood{\@ifnextchar_{\expandafter\@myRgood@\@gobble}{\mathrel{R^X}}}
\makeatother

\begin{document}

$a \myRbad b$

$a \myRbad_Y b$

$a \myRgood b$

$a \myRgood_Y b$

$a R^X_Y b$

$a \mathrel{R^X}_Y b$

$a \mathrel{R^X_Y} b$

\end{document}

Edit:

As a bonus, here is a macro that automates the creation of macros like \myRgood (using the improved method shown by @egreg's answer). (You have to \usepackage{xstring}.)

\makeatletter
\def\makeprocessedmathabsorbsubscript#1#2#3{
   \edef\@themacroname{\string#1}%
   \saveexpandmode%
   \fullexpandarg%
   \StrGobbleLeft{\@themacroname}{1}[\@themacroname]%
   \restoreexpandmode%
   \ifcsname\@themacroname\endcsname%
      \errmessage{The macro "\@themacroname" already exists}%
   \fi%
   \ifcsname @\@themacroname @\endcsname%
      \errmessage{Something strange is happening.
                  I want to create an internal macro for "\@themacroname",
                  but it exists already}%
   \fi%
   \expandafter\def\csname @\@themacroname @\endcsname##1##2{#2{#3_{##2}}}%
   \edef#1{%
      \unexpanded{\@ifnextchar_}%
         {\unexpanded\expandafter{\csname @\@themacroname @\endcsname}}%
         \unexpanded{{#2{#3}}}%
   }
}
\makeatother

Now one can write something like:

\makeprocessedmathabsorbsubscript{\myRbetter}{\mathrel}{R^X}

and the macro \myRbetter is provided.

share|improve this question

1 Answer 1

up vote 10 down vote accepted

Just define \@myRgood with two arguments and use the second one. When you call \@myRgood you know that _ follows.

\documentclass[a4paper]{amsart}

\makeatletter
\def\@myRgood@#1#2{\mathrel{R^X_{#2}}}
\def\myRgood{\@ifnextchar_{\@myRgood@}{\mathrel{R^X}}}
\makeatother

\begin{document}

$a \myRgood b$

$a \myRgood_Y b$

\end{document}

enter image description here

The “abstract” version; a trick similar to the one used for commands with optional arguments is used; the inner macro related to \myRgood is \\myRgood (with a backslash in its name).

\documentclass[a4paper]{amsart}

\makeatletter
\newcommand{\newrelation}[2]{% #1 = control sequence, #2 = replacement text
  \@ifdefinable{#1}{%
    \def#1{%
    \@ifnextchar_{\csname\string#1\endcsname}{\mathrel{#2}}%
    }%
    \@namedef{\string#1}##1##2{\mathrel{#2_{##2}}}%
  }%
}
\makeatother

\newrelation{\myRgood}{R^X}

\begin{document}

$a \myRgood b$

$a \myRgood_Y b$

\end{document}

A LaTeX3 version of the same

\documentclass[a4paper]{amsart}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\myRgood}{ }
 {
  \peek_catcode_remove:NTF \c_math_subscript_token
   { \hammerite_myR:n }
   { \hammerite_myR:n {} }
 }
\cs_new_protected:Npn \hammerite_myR:n #1
 {
  \mathrel
   {
    R^X
    \tl_if_empty:nF { #1 } { \c_math_subscript_token { #1 } }
   }
 }
\ExplSyntaxOff

\begin{document}

$a \myRgood b$

$a \myRgood_Y b$

\end{document}

Here's the “abstract” version

\documentclass[a4paper]{amsart}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\newrelation}{mm}
 {% #1 = control sequence, #2 = replacement text
  \NewDocumentCommand{#1}{}
   {
    \peek_catcode_remove:NTF \c_math_subscript_token
     {
      \hammerite_relation:nn { #2 }
     }
     {
      \hammerite_relation:nn { #2 } { }
     }
   }
 }

\cs_new_protected:Npn \hammerite_relation:nn #1 #2
 {
  \mathrel
   {
    #1
    \tl_if_empty:nF { #2 } { \c_math_subscript_token { #2 } }
   }
 }
\ExplSyntaxOff

\newrelation{\myRgood}{R^X}

\begin{document}

$a \myRgood b$

$a \myRgood_Y b$

\end{document}
share|improve this answer
    
Oh, good idea. I will leave this open a while in case anyone suggests an alternative method that is different entirely (e.g. doesn't use \@ifnextchar), but I expect I will end up accepting this answer. –  Hammerite Jan 17 at 12:40
    
@Hammerite I don't think there's a way to avoid \@ifnextchar or equivalent method. –  egreg Jan 17 at 13:51

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.