Is it possible to define an `\escape` command in LaTeX?
I think you just want \@namueuse
.
\@nameuse{foo}
becomes\foo
{\@nameuse{newcommand}}{\hi}{hi}
really means{\newcommand}{\hi}{hi}
, which is an error. But I think it is just an error in the question, and you intended\escape{newcommand}{\hi}{hi}
(without some braces).
Use
\makeatletter
\let\escape=\@nameuse
\makeatother
Or skip right into the simple definition of \@nameuse
\newcommand*\escape[1]{\csname #1\endcsname}
I can offer a macro \CsNameToCsToken
:
\CsNameToCsToken{foo}
→ \foo
.
(If this suits your needs you can replace \CsNameToCsToken
by \escape
. But I think the name "CsNameToCsToken" does better describe what the macro in question does.)
Syntax:
\CsNameToCsToken⟨stuff not in braces⟩{⟨NameOfCs⟩}
→
⟨stuff not in braces⟩\NameOfCs
(⟨stuff not in braces⟩
may be empty.)
Definition (in LaTeX 2ε):
\begingroup
\makeatletter
\@firstofone{%
\endgroup
\@ifdefinable\CsNameToCsToken{%
\long\def\CsNameToCsToken#1#{\romannumeral\InnerCsNameToCsToken{#1}}%
}%
\newcommand\InnerCsNameToCsToken[2]{%
\expandafter\exchange\expandafter{\csname#2\endcsname}{\z@#1}%
}%
\newcommand\exchange[2]{#2#1}%
}%
In plain-TeX
either also define
\z@
, e.g., to be a macro which expands to0⟨explicit space token⟩
, or to be a\dimendef
-token denoting a register holding length-value 0pt,or do:
\long\def\CsNameToCsToken#1#{\romannumeral0\InnerCsNameToCsToken{#1}}% \long\def\InnerCsNameToCsToken#1#2{% \expandafter\exchange\expandafter{\csname#2\endcsname}{ #1}% <- the space before #1 must be! }% \long\def\exchange#1#2{#2#1}%
(Due to \romannumeral
-expansion the result is obtained by triggering two expansion-steps, e.g., by having two "hits" with \expandafter
.)
With such a macro you are not bound to specific definition commands:
\CsNameToCsToken{foo}
→ \foo
.
\CsNameToCsToken\newcommand{foo}
→ \newcommand\foo
.
\CsNameToCsToken\DeclareRobustCommand{foo}
→ \DeclareRobustCommand\foo
.
\CsNameToCsToken\global\long\outer\def{foo}
→ \global\long\outer\def\foo
.
\CsNameToCsToken\expandafter{foo}\bar
→ \expandafter\foo\bar
.
\CsNameToCsToken\let{foo}=\bar
→ \let\foo=\bar
.
\CsNameToCsToken\string{foo}
→ \string\foo
.
\CsNameToCsToken\meaning{foo}
→ \meaning\foo
.
And here is the requested \NewDocumentCommand
-example:
With \NewDocumentCommand
you don't really need braces surrounding the control sequence token to define.
E.g.,
\NewDocumentCommand\foo{m}{foo's argument is: #1}
is the same as
\NewDocumentCommand{\foo}{m}{foo's argument is: #1}
Therefore you can do:
\CsNameToCsToken\NewDocumentCommand{foo}...
→ \NewDocumentCommand\foo...
.
You can as well use such a macro for defining/calling macros whose names contain spaces:
\CsNameToCsToken{foo }
→ \foo␣
.
\CsNameToCsToken\newcommand{foo }
→ \newcommand\foo␣
.
\CsNameToCsToken\DeclareRobustCommand{foo }
→ \DeclareRobustCommand\foo␣
.
\CsNameToCsToken\global\long\outer\def{foo }
→ \global\long\outer\def\foo␣
.
\CsNameToCsToken\expandafter{foo }\bar
→ \expandafter\foo␣\bar
.
\CsNameToCsToken\let{foo }=\bar
→ \let\foo␣=\bar
.
\CsNameToCsToken\string{foo }
→ \string\foo␣
.
\CsNameToCsToken\meaning{foo }
→ \meaning\foo␣
.
You can also nest the calls of \CsNameToCsToken
:
Example 1:
\CsNameToCsToken\CsNameToCsToken\expandafter{f o o }{b a r }
Processing the first \CsNameToCsToken
yields:
\CsNameToCsToken\expandafter\f␣o␣o␣{b a r }
.
Processing the second \CsNameToCsToken
yields:
\expandafter\f␣o␣o␣\b␣a␣r␣
.
(Analogously: \CsNameToCsToken\CsNameToCsToken\let{f o o }={b a r }
→ \let\f␣o␣o␣=\b␣a␣r␣
.)
Example 2:
\CsNameToCsToken\CsNameToCsToken\CsNameToCsToken\expandafter\expandafter\expandafter{f o o }\expandafter{b a r }{c r a z y }
Processing the first \CsNameToCsToken
yields:
\CsNameToCsToken\CsNameToCsToken\expandafter\expandafter\expandafter\f␣o␣o␣\expandafter{b a r }{c r a z y }
.
Processing the second \CsNameToCsToken
yields:
\CsNameToCsToken\expandafter\expandafter\expandafter\f␣o␣o␣\expandafter\b␣a␣r␣{c r a z y }
.
Processing the third \CsNameToCsToken
yields:
\expandafter\expandafter\expandafter\f␣o␣o␣\expandafter\b␣a␣r␣\c␣r␣a␣z␣y␣
.
Example 3:
In expansion contexts you can use \romannumeral
-expansion in order to keep things going.
\romannumeral\CsNameToCsToken\CsNameToCsToken\CsNameToCsToken\z@\expandafter\expandafter\expandafter{f o o }\expandafter{b a r }{c r a z y }
\romannumeral
triggers expansion until TeX has found a sequence of tokens that forms a ⟨number⟩-quantity. In the end TeX will find the ⟨number⟩-quantity \z@
whose value is 0
while with non-positive numbers \romannumeral
silently swallows the tokens forming the ⟨number⟩-quantity while not delivering any token at all:
%\romannumneral-expansion in progress
\CsNameToCsToken\CsNameToCsToken\CsNameToCsToken\z@\expandafter\expandafter\expandafter{f o o }\expandafter{b a r }{c r a z y }
Processing the first \CsNameToCsToken
yields:
%\romannumneral-expansion in progress
\CsNameToCsToken\CsNameToCsToken\z@\expandafter\expandafter\expandafter\f␣o␣o␣\expandafter{b a r }{c r a z y }
.
Processing the second \CsNameToCsToken
yields:
%\romannumneral-expansion in progress
\CsNameToCsToken\z@\expandafter\expandafter\expandafter\f␣o␣o␣\expandafter\b␣a␣r␣{c r a z y }
.
Processing the third \CsNameToCsToken
yields:
%\romannumneral-expansion in progress
\z@\expandafter\expandafter\expandafter\f␣o␣o␣\expandafter\b␣a␣r␣\c␣r␣a␣z␣y␣
.
Now \romannumeral
finds \z@
, i.e., the number 0
(in a way where no further digits and no to be discarded space-token terminating the ⟨number⟩ will be searched). Therefore \romannumeral
-expansion gets aborted and \romannumeral
won't deliver any token:
\expandafter\expandafter\expandafter\f␣o␣o␣\expandafter\b␣a␣r␣\c␣r␣a␣z␣y␣
.
Be aware that \CsNameToCsToken
internally applies \csname
while applying \csname
as a side effect yields assigning the control sequence in question the meaning of the \relax
-primitive in case the control sequence in question was undefined before applying \csname
. That assignment will be restricted to the current scope even if the \globaldefs
-parameter had a positive value at the time of applying \csname
.