如何在 Beamer 中重新定义 \emph 命令?

如何在 Beamer 中重新定义 \emph 命令?

我正在使用 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似乎执行以下操作:

  1. 保存原始定义
  2. 调用修改后的\newcommand

现在修改后的\newcommand调用内部调用原始的\newcommand,但它應該现在要做的是调用原始的\renewcommand。(顺便说一下,错误消息是因为原始命令\newcommand未在指定的命令上调用,在本例中是\emph,但同样,在顶部有一层包装来处理覆盖内容。)

因此,要解决这个问题:

  1. 向 beamer 维护人员发送电子邮件告知他们您发现了一个错误。
  2. 可以使用以下代码暂时修复此问题。基本上,我只是复制了处理代码\newcommand,并在所有情况下将“new”替换为“renew”,然而
  3. 给 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适合\renewcommands。

无论如何,这里是用 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

每个宏都支持覆盖规范,并具有相同的“签名”。因此,只需将一个宏用作另一个宏的别名即可。

相关内容