# Is it possible to use the substr package to extract the name of a command, then call that command?

Is it possible to use the substr package to extract the name of a command, then invoke that command? For example:

\newcommand{\abc}{yay}

\csname \BeforeSubString{|}{abc|def}\endcsname


What I want to see:

yay


What I see:

Missing \endcsname inserted. [\csname \BeforeSubString{|}{abc|def}]
Extra \endcsname. [...ame \BeforeSubString{|}{abc|def}\endcsname]

• \BeforeSubString is not expandable, so it won't work there. Do you need to use \BeforeSubString or some other command/package will do? – Phelype Oleinik Jun 27 at 1:33
• it can be any command that achieves that goal. any package is fine. – 14jbella Jun 27 at 1:33
• what does expandable/not expandable mean? – 14jbella Jun 27 at 1:34
• TeX works by expanding macros (for example, expanding \abc to yay), but some operations are not expandable, which means that they need to be processed in a deeper level by TeX. See the second part of this answer for a brief description of that. If you want to read more, then see this thread too. – Phelype Oleinik Jun 27 at 1:38
• hmm, so is it safe to say that string parsing is beyond the scope of latex? sorry I am new and don't know anything :) – 14jbella Jun 27 at 1:41

Here's an expandable version of \BeforeSubString which I (with all my creativity) called \ExpBeforeSubString:

\documentclass{article}

\makeatletter
\def\ExpBeforeSubString#1#2{%
\expandafter\befsub@detoki\expandafter{\detokenize{#2}}{#1}}
\def\befsub@detoki#1#2{%
\expandafter\befsub@detokii\expandafter{\detokenize{#2}}{#1}}
\def\befsub@detokii#1#2{%
\rn@ifsinglechar{#1}%
{\befsub@loop{}{#1}#2\q@rec@tail\q@rec@stop}%
{\errmessage{#1' should be a single, non-empty token.}}}
\def\q@rec@tail{\q@rec@tail}
\def\befsub@loop#1#2#3{%
\befsub@iftail{#3}%
{\befsub@return{#1}}%
{%
\befsub@match{#2}{#3}%
{\befsub@return{#1}}%
{\befsub@loop{#1#3}{#2}}%
}%
}
\def\befsub@match#1#2{%
\if#1#2%
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi}
\def\befsub@return#1#2\q@rec@stop{#1}
\def\befsub@iftail#1{%
\ifx\q@rec@tail#1%
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi}
\edef\rn@catofamp{\the\catcode\&}
\catcode\&=11
\long\def\rn@gobble#1&{%
\romannumeral-0\rn@@gobble#1\rn@qrtail &}
\long\def\rn@@gobble#1#2&{%
\ifx\rn@qrtail#1%
\expandafter\rn@@gobble@end
\else
\expandafter\rn@de@tail
\fi#2}
\def\rn@@gobble@end{ }
\long\def\rn@de@tail#1\rn@qrtail{ #1}
\long\def\rn@ifsinglechar#1{%
\rn@ifempty{#1}%
{\@secondoftwo}%
{%
\if\relax\expandafter\rn@gobble\detokenize{#1}&\relax
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}%
}
\catcode\&=\rn@catofamp
\long\def\rn@ifempty#1{%
\if\relax\detokenize{#1}\relax
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}
\makeatother

\begin{document}

\newcommand{\abc}{yay}
\csname \ExpBeforeSubString{|}{abc|def}\endcsname

\end{document}


Now using

\newcommand{\abc}{yay}
\csname \ExpBeforeSubString{|}{abc|def}\endcsname


yields yay. Yay!

Compare the length of code with the original (non expandable) version:

\makeatletter
\newcommand*\BeforeSubString[2]{%
\su@ExpandTwoArgs{#1}{#2}\su@BeforeSubString
}
\newcommand*\su@BeforeSubString[2]{%
\def\su@rest##1#1##2\@nil{##1}%
\IfSubStringInString{#1}{#2}{\su@rest#2\@nil}{#2}%
}
\newcommand\su@ExpandTwoArgs[3]{%
\protected@edef\su@SubString{#1}%
\protected@edef\su@String{#2}%
\expandafter\expandafter\expandafter#3%
\expandafter\expandafter\expandafter{%
\expandafter\su@SubString\expandafter
}\expandafter{\su@String}%
}
\newcommand*\IfSubStringInString[2]{%
\su@ExpandTwoArgs{#1}{#2}\su@IfSubStringInString
}
\newcommand*\su@IfSubStringInString[2]{%
\def\su@compare##1#1##2\@nil{%
\def\su@param{##2}%
\ifx\su@param\@empty
\expandafter\@secondoftwo
\else
\expandafter\@firstoftwo
\fi
}%
\su@compare#2\@nnil#1\@nil
}
\makeatother


Or a version with xstring which allows you to store the match in a temporary macro:

\documentclass{article}

\usepackage{xstring}

\begin{document}

\newcommand{\abc}{yay}
\StrBefore{abc|def}{|}[\tempmacro]
\csname\tempmacro\endcsname

\end{document}

• omg thank you so much!! I thought I was just asking a simple question, i guess latex is much less powerful than I expected! – 14jbella Jun 27 at 2:31
• sorry i am not allowed to vote up but if i could i would – 14jbella Jun 27 at 2:32
• @14jbella It's not that complicated, compared to other pieces of code out there. The first code has a bunch of security features to guarantee it will not explode, plus the extra complication for expandable code. You are facing this extra complication because you need/want expandability here, but you can always use the xstring version, which just requires an additional step. And I disagree, TeX can be quite powerful! Of course there are some things it simply can't do, but all languages have their limitations. (cont'd) – Phelype Oleinik Jun 27 at 2:59
• @14jbella If you want to give a try at programming in LaTeX, I suggest you take a look at expl3`. It's an attempt at providing a consistent programming API for LaTeX, which allows you do write some complicated code with relatively less effort. As I said, TeX can be quite powerful, you just have to get used to its oddities. Once you do, it's a quite fun procrastination tool :-) (P.S.: Don't worry about votes. However, you can mark the question as “solved” by clicking the check mark below it, if you want to.) – Phelype Oleinik Jun 27 at 3:02
• The are three things a man must do before his life is done; write two lines in expl3 and make the buggers run. (Stolen from The Devil's DP Dictionary, more or less). – John Kormylo Jun 27 at 4:13