如果您使用 定义,\bletter
它\DeclareRobustCommand\bletter[1]{\textbf{#1}}
甚至可以在部分命令中正常工作。但是如果您想在\edef
或\xdef
命令中使用它,\bletter
就会被破坏(除非您定义了\let\protect\noexpand
)。这意味着:
\xdef\boldyletter{\bletter{y}}
将抛出一条错误消息。
是否有任何命令可以定义始终牢不可破的命令?
答案1
您可以使用
\NewDocumentCommand\bletter{m}{\textbf{#1}}
这使得 e-tex \protected
定义不会在 edef 中扩展。
但是您永远不应该\xdef
在未知的乳胶输入上使用,使用\protected@xdef
后 LaTeX 强命令将受到保护。
答案2
只需使用\protected\def
原始声明即可\bletter
:
\protected\def\bletter#1{\textbf{#1}}
在、、等期间,宏\protected
不会扩展。\edef
\xdef
\write
\message
答案3
抱歉,我只能回答自己的问题,但我不知道如何与社区分享我的解决方案。
\def\RJDeclareRobustCommand#1% #1 name of new command, #2 same instructions as \newcommand
{%
\gdef#1%
{%
\begingroup%
\let\relax\aftergroup% this has to be redefined before processing \csname @\string#1\endcsname
\ifx\aftergroup\relax% this is false in expandations
\expandafter\aftergroup\csname RJ@\expandafter\@gobble\string#1\endcsname%
\else% \expandafter\aftergroup\expandafter\noexpand\csname\expandafter\@gobble\string#1@RJ\endcsname%
\fi%
\endgroup%
}%
\expandafter\gdef\csname\expandafter\@gobble\string#1@RJ\endcsname%
{%
\begingroup%
\let\relax\aftergroup% this has to be redefined before processing \csname @\string#1\endcsname
\ifx\aftergroup\relax% this is false in expandations
\expandafter\aftergroup\csname RJ@\expandafter\@gobble\string#1\endcsname%
\else%
\expandafter\aftergroup\expandafter\aftergroup\expandafter\aftergroup%
\expandafter\noexpand\csname\expandafter\@gobble\string#1@RJ\endcsname%
\fi%
\endgroup%
}%
% read the instructions (see \new@command)
\expandafter\new@command\csname RJ@\expandafter\@gobble\string#1\endcsname%
}%
%
\RJDeclareRobustCommand\bletter[1]{\textbf{#1}}
将会很强劲。
\xdef\boldyletter{\bletter{y}}
即使在命令中也能正常工作\xdef\boldxyletter{x\boldyletter}}
。
答案4
非常感谢这些非常有帮助的回答。它们对我来说也是一个挑战,我很乐意接受。
为了在章节标题中使用新命令,除其他事项外,还必须在 \pdfstringdef 中添加并重新定义该命令。我的旧代码没有考虑到这一点。添加此要求时,我还能够优化代码。
以下是使用新代码的测试示例。书签中将忽略新命令(而不是其参数)。
\documentclass[a4paper,12pt]{report}
\RequirePackage[pdftex,colorlinks,linkcolor=blue,%
urlcolor=blue,bookmarksnumbered]{hyperref}
%
\makeatletter
%
\let\RJ@aftergroup\aftergroup%
\let\RJ@begingroup\begingroup%
\let\RJ@endgroup\endgroup%
\let\RJ@let\let%
%
\@ifundefined{pdfstringdefPreHook}{}%
{%
\gdef\Addpdfstringdef#1%
{%
\global\@temptokena\expandafter%
{\pdfstringdefPreHook#1}%
\xdef\pdfstringdefPreHook{\the\@temptokena}%
}%
%
\Addpdfstringdef%
{%
\let\RJ@aftergroup\@empty%
\let\RJ@begingroup\@empty%
\let\RJ@endgroup\@empty%
\let\RJ@let\@empty%%
}%
}%
%
\def\RJ@DRCentry#1%
{%
\RJ@begingroup%
\RJ@let\relax\RJ@aftergroup%
\ifx\RJ@aftergroup\relax%
\expandafter\RJ@aftergroup\csname RJ@\expandafter\@gobble\string#1\endcsname%
\else%
\expandafter\noexpand\csname RJ\expandafter\@gobble\string#1JR\endcsname%
\fi%
\RJ@endgroup%
}%
%
\def\RJ@DeclareRobustCommand#1% #1 name of new command, #2 same instructions as \newcommand
{%
\gdef#1%
{%
\ifx\RJ@aftergroup\@empty%
\else%
\expandafter\RJ@DRCentry\expandafter#1%
\fi%
}%
%
\expandafter\gdef\csname RJ\expandafter\@gobble\string#1JR\endcsname%
{%
\ifx\RJ@aftergroup\relax%
\gdef\next{\RJ@DRCentry{#1}}%
\RJ@aftergroup\next%
\else%
\expandafter\noexpand\csname RJ\expandafter\@gobble\string#1JR\endcsname%
\fi%
}%
%
\@ifundefined{pdfstringdefPreHook}{}%
{%
\expandafter\Addpdfstringdef\expandafter%
{\expandafter\let\csname RJ\expandafter\@gobble\string#1JR\endcsname\@empty}%
}%
\expandafter\new@command\csname RJ@\expandafter\@gobble\string#1\endcsname%
}%
%
\RJ@DeclareRobustCommand\iletter[1]{\textit{\huge #1}}%
%
\xdef\yiletter{\iletter{y}}%
\xdef\xyiletter{\iletter{x}\yiletter}%
\xdef\xyziletter{\xyiletter\iletter{z}}%
\xdef\jiletter{\iletter{j\iletter{i}}}%
\begin{document}
\tableofcontents
\newpage
test \iletter{j\iletter{i}}, \jiletter{} test \iletter{a}, \yiletter, \xyiletter, \xyziletter{} test
\section{italic \iletter{y}, \xyziletter}
The following chapter heading is for comparison purposes only .
\section{italic \textit{\huge y}, \textit{\huge xyz}}
more text
\end{document}