使用可选参数修补命令或使用 \DeclareRobustCommand 声明

使用可选参数修补命令或使用 \DeclareRobustCommand 声明

重新定义命令以包含其自身(修补在 TeX 用语中)通常使用\let这个答案@egreg 说:

绝不在用定义的命令或用并具有可选参数定义的命令\let上使用。\DeclareRobustCommand\newcommand

因此一个自然的问题是应该在这种情况下我们该怎么办?

例如,我如何重新定义\bibitem以在其后添加另一个命令?这个:

\let\old@bibitem\bibitem
\def\bibitem{\old@bibitem\it}

不起作用,并且 \show\bibitem 会显示原因:

> \bibitem=macro:
->\@ifnextchar [\@lbibitem \@bibitem .

我该怎么做才能达到效果呢?

我宁愿不使用诸如这样的包,xpatch因为我正在修改其他人将使用的类,并且我尝试使用尽可能少的包以最大限度地减少可能的冲突。

答案1

该命令\bibitem参数,更不用说可选参数了。我在回答的引用部分中引用的命令是使用

\newcommand{<macro>}[<args>][<default>]{...}

没有其他以间接方式定义的,\@ifnextchar或者\@ifstar\bibitem\section

如果您的目的是以斜体打印引用标签,那么\bibitem独立于任何包(例如etoolboxxpatchletltxmacro您加载的)进行修补都是错误的选择。

你能做什么?让我们看看:\bibitem有你展示的定义,所以我们知道我们必须修补\@lbibitem\@bibitem

利用texdef我们看到

> texdef -t latex -s @lbibitem
% latex.ltx, line 6228:
\def\@lbibitem[#1]#2{\item[\@biblabel{#1}\hfill]\if@filesw
      {\let\protect\noexpand
       \immediate
       \write\@auxout{\string\bibcite{#2}{#1}}}\fi\ignorespaces}

> texdef -t latex -s @bibitem
% latex.ltx, line 6232:
\def\@bibitem#1{\item\if@filesw \immediate\write\@auxout
       {\string\bibcite{#1}{\the\value{\@listctr}}}\fi\ignorespaces}

嗯。有两种情况:如果\bibitem后面跟着[,我们需要看看是如何\@biblabel定义的,然后我们会看到

> texdef -t latex -s @biblabel
% latex.ltx, line 6278:
\def\@biblabel#1{[#1]}

所以我们只需要做

\def\@biblabel#1{[\textit{#1}]}

如果没有可选参数,我们需要看看环境enumerate启动时的标准标签\begin{thebibliography}是如何定义的。很好:

> texdef -t latex -s thebibliography
% article.cls, line 575:
\newenvironment{thebibliography}[1]
     {\section*{\refname}%
      \@mkboth{\MakeUppercase\refname}{\MakeUppercase\refname}%
      \list{\@biblabel{\@arabic\c@enumiv}}%
           {\settowidth\labelwidth{\@biblabel{#1}}%
            \leftmargin\labelwidth
            \advance\leftmargin\labelsep
            \@openbib@code
            \usecounter{enumiv}%
            \let\p@enumiv\@empty
            \renewcommand\theenumiv{\@arabic\c@enumiv}}%
      \sloppy
      \clubpenalty4000
      \@clubpenalty \clubpenalty
      \widowpenalty4000%
      \sfcode`\.\@m}
     {\def\@noitemerr
       {\@latex@warning{Empty `thebibliography' environment}}%
      \endlist}

嗯,这取决于类别;我们假设类别是article。很好!标签仍使用打印\@biblabel,因此上述技巧在两种情况下都适用。

所以你的任务只是添加

\def\@biblabel#1{[\textit{#1}]}

到您的个人样式文件;如果必须在文档序言中完成修补,请确保在\makeatletter和之间添加行\makeatother(请参阅\makeatletter 和 \makeatother 起什么作用?)。然而这可能取决于类别,但通常人们可以依赖这一事实来\@biblabel改变它。

不,修补命令绝对不容易。

相关内容