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.

This question already has an answer here:

This is probably obvious to the TeX gurus, but here goes:

I want to create a command that takes a control sequence (with no arguments) as input and prints the name of that control sequence, without the leading backslash. How can that be done?

share|improve this question
    
It is done with \meaning see tex.stackexchange.com/questions/4784/… –  Yiannis Lazarides Mar 2 '13 at 10:15
1  
I thought \newcommand*{\MacroName}[1]{\string#1} should do it, but there seems to be an extra quote in the output? –  Peter Grill Mar 2 '13 at 10:16
    
@PeterGrill: Load usepackage[T1]{fontenc} and the quote will be a slash. –  Marco Daniel Mar 2 '13 at 10:19
    
@PeterGrill: Jubobs want no leading slash. –  Marco Daniel Mar 2 '13 at 10:21
add comment

marked as duplicate by Leo Liu, lockstep, Stefan Kottwitz Mar 2 '13 at 11:48

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

2 Answers

up vote 7 down vote accepted

There are various approaches, as some of the comments indicate. There are a couple of 'awkward' cases to cover: if the escape character is non-printable, and if the control sequence starts with a space (such as \csname\space awkward\endcsname). In expl3, we cover this with a function called \cs_to_str:N, which in primitives would be written as

\catcode`\@=11 %
\def\cs@to@str{%
  \romannumeral\if\string\ \cs@to@str@aux@i\fi
    \expandafter\cs@to@str@aux@ii\string
}
\long\def\cs@to@str@aux@i#1\cs@to@str@aux@ii{%
  -\number\fi\expandafter\z@
}
\long\def\cs@to@str@aux@ii#1{\z@}

and used as

\cs@to@str\foo % => "foo"
\expandafter\cs@to@str\csname\space foo\endcsname % => " foo"

To explain how this works, there are three cases

  1. The escape character is printable and not a space. In this case, \string\ gives two tokens (the escape character and a space), which have different catcodes. The \if test is therefore false, and so the second \string can safely be used, with \cs@to@str@aux@ii removing the escape character.

  2. The escape character is not printable. In this case, \string\ yields only one token, and the test continues, expanding \cs@to@str@aux@i. The insertion of - forces the test to be false and \string can be used directly to give the desired output.

  3. The escape character is a space. In this case, the \if test is true, and \cs@to@str@aux@i leads to the insertion of -\z@ which \number turns into -0. That's not 'terminated', so the \romannumeral goes looking for an optional space. It finds this in the escape character, which is therefore removed leaving just the control sequence name.

In all three cases, notice that we never have the possibility to remove a leading space from the name itself as we never remove a token that is not the escape character.


As this is all built-in to expl3, I'd just create a document-level alias:

\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\newcommand{\CsToStr}[1]{\cs_to_str:N #1}
\ExplSyntaxOff
\begin{document}
\CsToStr{\LaTeX}

\CsToStr{\def} 

\CsToStr{\newcommand}

\CsToStr{\MacroName}
\end{document}

(you can do this with xparse, of course).

share|improve this answer
    
A small expl-solution would be nice. I am thinking about a solution which accepts strings and commands. –  Marco Daniel Mar 2 '13 at 10:37
    
@MarcoDaniel I've added an expl3 version: a command taking both strings and command names seems like a poor idea to me (what is the formal definition for the interface?). –  Joseph Wright Mar 2 '13 at 10:42
    
I am only interested in an implementation ;-) –  Marco Daniel Mar 2 '13 at 10:44
    
@MarcoDaniel The version I have above is the same as the expl3 implementation except for the naming conventions: see l3basics.dtx. –  Joseph Wright Mar 2 '13 at 10:50
add comment

You can also use the xstring package along with \string:

enter image description here

Code:

\documentclass{article}
\usepackage{xstring}

\newcommand*{\MacroName}[1]{\StrGobbleLeft{\string#1}{1}}%

\begin{document}
\MacroName{\LaTeX}

\MacroName{\def} 

\MacroName{\newcommand}

\MacroName{\MacroName}
\end{document}
share|improve this answer
    
Fails if the escape character is non-printable (try \escapechar=-1 just after \begin{document}). –  Joseph Wright Mar 2 '13 at 10:36
1  
@JosephWright I would say the other way around: make \escapechar=-1 and forget xstring. –  tohecz Mar 2 '13 at 10:47
    
Not considering the \escapechar=-1 issue you can achieve the same without xstring: \makeatletter\newcommand{\MacroName}[1]{\expandafter\@gobble\string#1}\makeatot‌​her –  cgnieder Mar 2 '13 at 14:36
    
Also you should use the non-starred variant of \newcommand or you can't use \MacroName{\par}. –  cgnieder Mar 2 '13 at 14:38
add comment

Not the answer you're looking for? Browse other questions tagged or ask your own question.