7

I would like to know if it is possible to make \csname ignore subscript symbols. Below is a MWE of what I mean by that:

\documentclass[a4paper,11pt]{book}

% I have several commands with the same prefix
\newcommand{\fooT}{T}
\newcommand{\fooS}{S}

% I want to call these commands from another command with respect to the given parameter
\newcommand{\fooL}[1]{L_{\csname foo#1\endcsname}}

\begin{document}
Without subscript $\fooL{T}$ gives the same thing than $L_{\fooT}$.


With subscript $\fooL{T_j}$ is different from $L_{\fooT_j}$.
\end{document}

From what I understood this behaviour is to be expected since \csname will expand everything to a single command named \fooT_j with _ considered as a part of the name and not the subscript character. Is it possible to change this behaviour such that \csname returns the command \fooT with the subscript _j ? In other words I want $\fooL{T_j}$ to give the same thing than $L_{\fooT_j}$.

I tried to play around with the \detokenize and \scantokens commands:

\newcommand{\fooL}[1]{L_{\expandafter\scantokens{\expandafter\detokenize{\csname foo#1\endcsname}}}}

but I did not manage to obtain something satisfying. The idea was to break down the command and then reconstruct it.

I am aware that I could change the syntax of the commands to obtain the desired result but it would be more convenient for me to keep the same syntax.

5
\documentclass[a4paper,11pt]{book}

% I have several commands with the same prefix
\newcommand{\fooT}{T}
\newcommand{\fooS}{S}

% I want to call these commands from another command with respect to the given parameter
\newcommand{\fooL}[1]{\fooLhelp#1\relax}
\def\fooLhelp#1#2\relax{L_{\csname foo#1\endcsname#2}}

\begin{document}
Without subscript $\fooL{T}$ gives the same thing than $L_{\fooT}$.


With subscript $\fooL{T_j}$ is different from $L_{\fooT_j}$.
\end{document}

enter image description here

Manuel's suggestion streamlines the approach still further:

\newcommand*\fooL[1]{L_{\auxfoo#1}}
\newcommand*\auxfoo[1]{\csname foo#1\endcsname}

since \auxfoo will only grab the first token of the argument.


ADDENDUM

Some comment discussion occurred for cases where the underlying \foox macro occurs when x is more than a single token. Manuel noted that such cases can be addressed in a limited way, under the proviso that underlying macro only appears by itself or followed by a subscript.

Here is how that would be done:

\documentclass[a4paper,11pt]{book}

% I have several commands with the same prefix
\newcommand{\fooT}{T}
\newcommand{\fooTTT}{TTT}
\newcommand{\fooS}{S}

% I want to call these commands from another command with respect to the given parameter
\newcommand{\fooL}[1]{\fooLhelp#1_\relax}
\def\fooLhelp#1_#2\relax{L_{\csname foo#1\endcsname\ifx\relax#2\relax\else_\foolHelp#2\fi}}
\def\foolHelp#1_{#1}

\begin{document}
Without subscript $\fooL{T}$ gives the same thing than $L_{\fooT}$.


With subscript $\fooL{T_j}$ is different from $L_{\fooT_j}$.


With longer base $\fooL{TTT}$ and subscript $\fooL{TTT_j}$.
\end{document}

enter image description here

4
  • 1
    There's no need to have delimited arguments. Just define \fooLhelp with one argument and it will take the first token of #1. I'll remove my answer. – Manuel Sep 22 '16 at 12:10
  • Thank you. It solves my problem perfectly. If I may and if I am not mistaken if one want to define a command \newcommand{fooTT}{TT}, i.e. with several suffix characters, then \fooL{TT_j} will not work properly and one has to call \fooL{{TT}_j} instead. – M. P. Sep 22 '16 at 12:43
  • @M.P. That is correct. As written, it will only pick up a single token. The problem with a multi-letter solution is in knowing where to end the string automatically. So the grouped approach you suggest is the safest alternative. – Steven B. Segletes Sep 22 '16 at 12:45
  • @M.P. If the only “weird” thing that might appear in \fooL{FOO_0} is a subscript, you can actually make the macro intelligent so that it takes every character until the _. – Manuel Sep 22 '16 at 14:02
4

When using \csname you always risk to get unexpected results, so I add also error checking.

\documentclass{article}

\newcommand{\fooT}{\mathcal{T}}
\newcommand{\fooS}{\mathbf{S}}
\newcommand{\fooST}{\mathrm{ST}}

\makeatletter
\newcommand{\fooL}[1]{\fooL@aux#1_\fooL@aux}
\def\fooL@aux#1_#2\fooL@aux{%
  \ifcsname foo#1\endcsname
    \csname foo#1\endcsname
  \else
    \@latex@error{Wrong argument}{The 'foo#1' command does not exist}%
  \fi
  \if\relax\detokenize{#2}\relax
    % no _ in the argument
  \else
    \fooL@aux@i#2% remove the surplus _
  \fi
}
\def\fooL@aux@i#1_{_{#1}}
\makeatother

\begin{document}
$\fooL{T}$ and $\fooL{T_j}$

$\fooL{S}$ and $\fooL{S_jkl}$

$\fooL{ST}$ and $\fooL{ST_j}$

$\fooL{X}$
\end{document}

This gives

enter image description here

and also the following messages on the console:

! LaTeX Error: Wrong argument.

See the LaTeX manual or LaTeX Companion for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.31 $\fooL{X}
              $
? h
The 'fooX' command does not exist
? 

An expl3 implementation:

\documentclass{article}
\usepackage{xparse}

\newcommand{\fooT}{\mathcal{T}}
\newcommand{\fooS}{\mathbf{S}}
\newcommand{\fooST}{\mathrm{ST}}

% look for _ in the argument    
\NewDocumentCommand{\fooL}{>{\SplitArgument{1}{_}}m}{\fooLaux#1}

\ExplSyntaxOn
\NewDocumentCommand{\fooLaux}{mm}
 {
  \cs_if_exist:cTF { foo#1 }
   {
    \use:c { foo#1 }
   }
   {
    \msg_error:nnn { mp } { foo-not-exist } { #1 }
   }
  % if _ is found, argument #2 has value
  \IfValueT{#2}{\sb{#2}}
 }
% define the error message
\msg_new:nnnn { mp } { foo-not-exist }
 {
  Wrong~argument
 }
 {
  The~command~'foo#1'~does~not~exist
 }
\ExplSyntaxOff

\begin{document}
$\fooL{T}$ and $\fooL{T_j}$

$\fooL{S}$ and $\fooL{S_jkl}$

$\fooL{ST}$ and $\fooL{ST_j}$

$\fooL{X}$
\end{document}

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.