嵌套使用 \ifcsname 需要保护

嵌套使用 \ifcsname 需要保护

我有一个宏,\command用于确保文档中宏的名称格式一致。一直效果很好,直到我有一种拖延的冲动,才有了这杰出的我可以通过检查宏是否存在,轻松捕获宏名称的大多数拼写错误。

看起来很简单。所以我补充道:

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

到执行格式化的宏,其中#1是宏的名称。这在基本情况下似乎工作正常,如下面的 MWE 所示,它产生:

在此处输入图片描述

并正确地告诉我bfseriess\foo未定义。

但是,如果我尝试以嵌套方式使用它

\command{foo=\command{MyDef}}

我收到错误消息

Missing \endcsname inserted.

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

问题:

我感觉解决方案就在参考文献中列出的问题中,但我不知道具体怎么做\protect。那么,我可以对宏进行哪些更改,\command以便我可以取消注释 MWE 中的最后一行并显示正确的错误消息。

参考:

代码:

\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}

答案1

当参数\command不是命令名时,我完全不确定预期的行为是什么,但是这会做一些事情:

在此处输入图片描述

\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}

或者根据评论中的要求进行更新,以删除之前的论点=

在此处输入图片描述

\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}

答案2

\doifundefined通过简单地模仿ConTeXt 中的定义(在文件中定义syst-gen.mkii),添加\detokenize定义就可以了。

\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%
}% 

在此处输入图片描述

答案3

我会选择类似的东西:

\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}

请注意,当您检查“嵌套”命令时,实际上代码会检查:

  foo=\command{MyDef}

是一个定义的宏!使用csname... endcsname,可以使用任意字符的任意命令。!$%.#!.o>,p\def}例如,您可以有一个命令。您可以将以下代码片段添加到演示该概念的示例中。

\expandafter\def\csname My$Def\endcsname{MyDef...}

\mytypeset{My$Def}

% prints MyDef...
\csname My$Def\endcsname

\My$DefMyDef..now 是一个命令,执行时会打印。

相关内容