我正在使用 Beamer 类,并希望重新定义\emph
为使用\bfseries
而不是\itshape
。我尝试了以下命令:
\renewcommand<>{\emph}[1]{{\only#2{\bfseries}#1}}
但我收到以下错误
! LaTeX Error: Command \beamerx@\emph already defined.
Or name \end... illegal, see p.192 of the manual.
\emph
我不明白:为什么当我使用时它已经是一个定义好的问题了?\renewcommand
答案1
查看代码,我认为这是一个错误。Beamer 定义了一个包装器来包装\newcommand
和\renewcommand
环境,当使用以下 调用它们时,它们会介入<>
。但 new\renewcommand
似乎执行以下操作:
- 保存原始定义
- 调用修改后的
\newcommand
现在修改后的\newcommand
调用内部调用原始的\newcommand
,但它應該现在要做的是调用原始的\renewcommand
。(顺便说一下,错误消息是因为原始命令\newcommand
未在指定的命令上调用,在本例中是\emph
,但同样,在顶部有一层包装来处理覆盖内容。)
因此,要解决这个问题:
- 向 beamer 维护人员发送电子邮件告知他们您发现了一个错误。
- 你可以使用以下代码暂时修复此问题。基本上,我只是复制了处理代码
\newcommand
,并在所有情况下将“new”替换为“renew”,然而 - 给 beamer 维护人员发邮件,告诉他们修复这个错误后又发现了一两个错误!当我使用上面的代码时,我得到了一些关于命令未定义的错误。我对此的解释是,beamer
\begin{document}
使用 做了一些重新定义(当时)\renewcommand
。在旧版本中,如果要重新定义的命令是不是如果当前已定义,则此操作将顺利通过。但是,在新版本中,如果要重新定义的命令当前未定义,则会产生错误!(有问题的命令是\includegraphics
和\pgfuseimage
。)
无论如何,以下是解决方法。使用时请自担风险:
\makeatletter
\def\renewcommand{\@ifnextchar<{\beamer@renewcom}{\beamer@origrenewcommand}}
\def\beamer@renewcom<>{\@star@or@long\beamer@renew@command}
\def\beamer@renew@command#1{\@ifnextchar[{\beamer@@renewcom{#1}}{\beamer@renewcomnoopt
{#1}{0}}}
\def\beamer@@renewcom#1[#2]{\@ifnextchar[{\beamer@renewcomopt{#1}{#2}}{\beamer@renewcomnoopt{#1}{#2}}}
\long\def\beamer@renewcomnoopt#1#2#3{%
\ifnum#2=0\relax%
\expandafter\def\expandafter#1\expandafter{\expandafter\beamer@sortzero\expandafter{\csname beamerx@\string#1\endcsname}}%
\else
\expandafter\def\expandafter#1\expandafter{\expandafter\beamer@sort\expandafter{\csname beamerx@\string#1\endcsname}{#2}}%
\fi%
\beamer@argscount=#2\relax%
\advance\beamer@argscount by 1\relax%
\expandafter\renewcommand\csname beamerx@\string#1\endcsname[\beamer@argscount]{#3}%
}
\long\def\beamer@renewcomopt#1#2[#3]#4{%
\expandafter\def\expandafter#1\expandafter{\expandafter\beamer@presort\expandafter{\csname beamerx@\string#1\endcsname}{#2}{#3}}%
\beamer@argscount=#2\relax%
\advance\beamer@argscount by 1\relax%
\expandafter\renewcommand\csname beamerx@\string#1\endcsname[\beamer@argscount]{#4}%
}
\makeatother
(在编辑中添加): 我在上面的代码中犯了一个错误:它没有保存命令的原始版本,而 Beamer 版本保存了该命令\renewcommand
。此外,由于存在冲突,我认为实际上定义一个\myrenewcommand
执行该命令的命令会更好。因此下面的代码可能更好。它可能还远未达到完美 - 例如,我不知道是否\@star@or@long
适合\renewcommand
s。
无论如何,这里是用 MWE 包装的版本 2:
\documentclass{beamer}
% http://tex.stackexchange.com/q/13726/86
\makeatletter
\def\myrenewcommand{\@ifnextchar<{\beamer@myrenewcom}{\beamer@origrenewcommand}}
\def\beamer@myrenewcom<>{\@star@or@long\beamer@myrenew@command}
\def\beamer@myrenew@command#1{%
\expandafter\def\expandafter\beamer@name\expandafter{\csname @orig\string#1\endcsname}%
\expandafter\let\beamer@name=#1\relax%
\@ifnextchar[{\beamer@@myrenewcom{#1}}{\beamer@myrenewcomnoopt
{#1}{0}}}
\def\beamer@@myrenewcom#1[#2]{\@ifnextchar[{\beamer@myrenewcomopt{#1}{#2}}{\beamer@myrenewcomnoopt{#1}{#2}}}
\long\def\beamer@myrenewcomnoopt#1#2#3{%
\ifnum#2=0\relax%
\expandafter\def\expandafter#1\expandafter{\expandafter\beamer@sortzero\expandafter{\csname beamerx@\string#1\endcsname}}%
\else
\expandafter\def\expandafter#1\expandafter{\expandafter\beamer@sort\expandafter{\csname beamerx@\string#1\endcsname}{#2}}%
\fi%
\beamer@argscount=#2\relax%
\advance\beamer@argscount by 1\relax%
\expandafter\renewcommand\csname beamerx@\string#1\endcsname[\beamer@argscount]{#3}%
}
\long\def\beamer@myrenewcomopt#1#2[#3]#4{%
\expandafter\def\expandafter#1\expandafter{\expandafter\beamer@presort\expandafter{\csname beamerx@\string#1\endcsname}{#2}{#3}}%
\beamer@argscount=#2\relax%
\advance\beamer@argscount by 1\relax%
\expandafter\renewcommand\csname beamerx@\string#1\endcsname[\beamer@argscount]{#4}%
}
\makeatother
\myrenewcommand<>{\emph}[1]{{\only#2{\bfseries}#1}}
\newcommand<>{\test}[1]{{\only#2{\bfseries}#1}}
\begin{document}
\begin{frame}
Some \emph{emphasised} text
\end{frame}
\end{document}
答案2
如果您想要做的只是加粗\emph
其文本,您可以这样做:
\let\emph\textbf
每个宏都支持覆盖规范,并具有相同的“签名”。因此,只需将一个宏用作另一个宏的别名即可。