# Nested use of \ifcsname needs protection

I have a macro \command to ensure that the names of macros in my documentation are consistently formatted. Been work great, until I had an urge to procrastinate and had this brilliant idea that I can easily catch most spelling errors of the macro names, by checking that the macro exists.

Seems simple enough. So I added:

\ifcsname#1\endcsname%
\else%
\par\textbf{\textcolor{red}{\textbackslash#1} is not defined.}
\fi%


to the macro that does the formating, where #1 is the name of the macro. This seems to work fine in the basic case as illustrated by the MWE below that produces:

and correctly tells me that bfseriess and \foo are not defined.

However, if I attempt to use this in a nested fashion

\command{foo=\command{MyDef}}


I get the error message

Missing \endcsname inserted.

<to be read again>
\protect
l.25 \command{foo=\command{MyDef}}


## Question:

I have a feeling that the solution is in the question listed in the references but I don't know exactly how to \protect things. So, what changes can I make to the \command macro so that I can uncomment the last line in the MWE and the proper error messages.

## Code:

\documentclass{article}
\usepackage{xcolor}

%% The last line should not produce any error
%% messages (red text) if these two are defined.
%
%\newcommand*{\foo}{}%
%\newcommand*{\MyDef}{}%

\newcommand{\command}[1]{%
\textbf{\textbackslash#1}%
%% Since this is used to typeset macro names, we
%% can check for typos by ensuring the macro exists
\ifcsname#1\endcsname%
\else%
\par\fcolorbox{red}{red!20}{\textcolor{blue}{\textbackslash#1} is not defined.}
\fi%
}%

\begin{document}
To bold text use \command{textbf} or \command{bfseriess}.

A useful token is \command{foo}.

This token needs to be set with:
%\command{foo=\command{MyDef}}
\end{document}

-
This is not due to nested \ifcsname. For example, if you change the definition to \newcommand\command[1]{(#1 is \ifcsname#1\endcsname \else not \fi defined)} then the document compiles correctly. –  Aditya Jan 21 '13 at 1:55
@Aditya: Hmmm, you are indeed correct. So its just my fancy formatting that is getting the way somehow? –  Peter Grill Jan 21 '13 at 1:57
Yes, but I don't know the LaTeX internals well to explain why that is happening. –  Aditya Jan 21 '13 at 1:59
@Aditya: Yeah, thought it was a simple matter of adding a few \protects here and there, but haven't guessed the correct sequence yet. –  Peter Grill Jan 21 '13 at 2:00
The problem is the \protect that's hidden in the definition of \textbf. You can trigger the error message e.g. with \DeclareRobustCommand\foo{}\csname\foo\endcsname –  cgnieder Jan 21 '13 at 10:16

I'm not at all sure what the intended behaviour is when the argument to \command isn't a command name, but this does something:

\documentclass{article}
\usepackage{xcolor}

%% The last line should not produce any error
%% messages (red text) if these two are defined.
%
%\newcommand*{\foo}{}%
%\newcommand*{\MyDef}{}%

\protected\def\command#1{%
\textbf{\textbackslash#1}%
%% Since this is used to typeset macro names, we
%% can check for typos by ensuring the macro exists
\ifcsname\detokenize{#1}\endcsname%
\else%
\par\fcolorbox{red}{red!20}{\textcolor{blue}{\textbackslash#1} is not defined.}
\fi%
}%

\begin{document}
To bold text use \command{textbf} or \command{bfseriess}.

A useful token is \command{foo}.

This token needs to be set with:
\command{foo=\command{MyDef}}
\end{document}


Or updated as requested in comments to strip the argument before =

\documentclass{article}
\usepackage{xcolor}

%% The last line should not produce any error
%% messages (red text) if these two are defined.
%
%\newcommand*{\foo}{}%
%\newcommand*{\MyDef}{}%

\protected\def\command#1{%
\textbf{\textbackslash#1}%
%% Since this is used to typeset macro names, we
%% can check for typos by ensuring the macro exists
\ifcsname\expandafter\beforeeq\detokenize{#1}=\beforeeq\endcsname%
\else%
\par\fcolorbox{red}{red!20}{\textcolor{blue}{\textbackslash\expandafter\beforeeq\detokenize{#1}=\beforeeq} is not defined.}
\fi%
}%

\def\beforeeq#1=#2\beforeeq{#1}

\begin{document}
To bold text use \command{textbf} or \command{bfseriess}.

A useful token is \command{foo}.

This token needs to be set with:
\command{foo=\command{MyDef}}
\end{document}

-
For the nested usage, I would like to be able to use something like \StrBefore{\detokenize{#1}}{=}[\MacroName] so that I could check for \ifcsname\MacroName\endcsname but can't quite figure how to get that to work in this case. –  Peter Grill Jan 21 '13 at 12:05
@PeterGrill so in this example you want to test for foo? (This seems a very odd requirement:-) (Update on way....) –  David Carlisle Jan 21 '13 at 12:14
I agree that is strange, but I am only trying to make it work for the cases I need, not a general solution as this is for internal documentation purposes. This does indeed work as I need but was hoping that it used xstring so that I could easily expand it if needed to handle other cases. –  Peter Grill Jan 21 '13 at 21:39

By simply imitating the definition of \doifundefined from ConTeXt (defined in file syst-gen.mkii), adding \detokenize to the definition works.

\newcommand\command[1]
{\textbf{\textbackslash#1}%
%% Since this is used to typeset macro names, we
%% can check for typos by ensuring the macro exists
\ifcsname\detokenize{#1}\endcsname%
\else%
\par\fcolorbox{red}{red!20}{\textcolor{blue}{\textbackslash#1} is not defined.}
\fi%
}%


-
When you uncomment the \newcommands, the macro is checking if \csname foo=\textbf{\textbackslash MyDef}\endcsname is defined or not. Clearly, that montrosity is not defined. –  Aditya Jan 21 '13 at 6:30
Yeah that is what I meant about precusse's comment. I need to rethink how to handle the nested case properly. –  Peter Grill Jan 21 '13 at 7:30

I would go for something like:

\documentclass{article}
\begin{document}
\makeatletter
\def\mytypeset#1{%
\def\command##1{%
\ifcsname##1\endcsname%
\expandafter\@firstoftwo
\else%
\expandafter\@secondoftwo
\fi%
}%
\def\z{\detokenize{#1}}
\command{\z}{\fbox{TRUE}}{\fbox{FALSE}}
}

\mytypeset{deff{f}f}

\mytypeset{def}

\mytypeset{foo=\command{MyDef}}
\end{document}


Note that when you are checking for a "nested" command, as a matter of fact the code checks to see if:

  foo=\command{MyDef}


is a defined macro! With csname...endcsname, arbitrary commands of any characters ca be used. You can have a command !$%.#!.o>,p\def} for example. You can add the follow snippet to the example that demonstrates the concept. \expandafter\def\csname My$Def\endcsname{MyDef...}

\mytypeset{My$Def} % prints MyDef... \csname My$Def\endcsname


\My\$Def now is a command and prints MyDef.., when executed.

-
Yeah, am trying to figure out how to handle the nested case since what I initially put together would fail miserably for that case. –  Peter Grill Jan 21 '13 at 9:11
@PeterGrill ...tricky stuff! : –  Yiannis Lazarides Jan 21 '13 at 9:16