For indexing I wanted to write a macro \macroname
that removes leading backslashes from macro names but leaves the names of environments untouched. That is
\macroname{\relax} --> relax
\macroname{itemize} --> itemize
where the -->
is meant to be read as "expands to".
From my understanding, the following should work:
\newcommand\removebs[1]{\if#1\char92\else#1\fi}
\newcommand\macroname[1]{%
\expandafter\removebs\detokenize{#1}}
However, its outcome is
\macroname{\relax} --> \relax % literally
\macroname{itemize} --> itemize
By chance, actually, I found out that if I change the catcode of the backslash to "other" during the definition of the \removebs
macro, it works:
{
\catcode`\|=0
|catcode`|\=12
|global|def|removebs#1{|if#1\|else#1|fi}
}
\newcommand\macroname[1]{%
\expandafter\removebs\detokenize{#1}}
Why is that? From TeX by Topic I'd expect that the comparison made by \if
is what Philipp Lehman calls "category code agnostic".
Thanks for your answers!
Best Answer
Joseph has given a working solution. I'd like to explain what goes wrong with your code.
First attempt
With
\macroname{\relax}
you getand then (using
•
to separate tokens and<space>
do denote a space token)which becomes
and the comparison is between a category code 12 backslash and the token
\char
, which of course leads to false.The code
\char92
are instruction to print character 92 from the current font.One might correct the code by checking against a real category code 12 backslash:
but the space produced by
\detokenize
after\relax
would remain.Second attempt
This works because it just implements the check against a category code 12 backslash, but it's not necessary, as the token is already available as
\@backslashchar
in the LaTeX kernel.An alternative way, without global definitions and category changes, can be
where the only token that is converted to its lowercase equivalent is
|
(to a backslash).Proposed code
Since all you want is to get the argument letters, it doesn't matter if the first letter in
\macroname{itemize}
has category code 12.