10

I am using the Beamer class and would like to redefine \emph to use \bfseries instead of \itshape. I have tried the following command:

\renewcommand<>{\emph}[1]{{\only#2{\bfseries}#1}}

but I get the following error

! LaTeX Error: Command \beamerx@\emph already defined.
          Or name \end... illegal, see p.192 of the manual.

I cannot understand: Why is it a problem that \emph already is defined when I am using \renewcommand?

lockstep
  • 250,273
  • The code has two problems: a) spurious <>; b) inconsistent parameter number (1 declared, 2 used). Perhaps you could comment on what is the new \emph supposed to do — this would make things clearer. – Andrey Vihrov Mar 17 '11 at 13:15
  • 6
    The <> is not spurious. According to the beamer manual (page 86 in version 3.10), you can redefine an existing command by \renewcomamnd<>\cmd[1]{...}. The second parameter stores the overlay specification. – Michael Ummels Mar 17 '11 at 13:21
  • @Michael: My bad. Thanks for the explanation! – Andrey Vihrov Mar 17 '11 at 13:24

2 Answers2

15

Looking at the code, I'd say that this was a bug. Beamer defines a wrapper around the \newcommand and \renewcommand environments which step in when they are called with a following <>. But the new \renewcommand seems to do the following:

  1. Save the original definition
  2. Call the modified \newcommand

Now the modified \newcommand calls internally calls the original \newcommand but what it ought to do here is now call the original \renewcommand. (The error message, by the way, is because the original \newcommand is not called on the command specified, in this case \emph, but again there's a level of wrapping on top to deal with the overlay stuff.)

So, to fix this:

  1. Email the beamer maintainers informing them that you think you've found a bug.
  2. You could use the following code to temporarily fix this problem. Basically, I've just copied out the code that handles \newcommand and replace "new" by "renew" at all instances, however
  3. Email the beamer maintainers to say that fixing this bug reveals one or two more! When I use the above code then I get a few errors about commands not being defined. My interpretation of this is that beamer does a few redefinitions (at the \begin{document} time) using \renewcommand. With the old version, if the command-to-be-redefined is not currently defined then this goes through just fine. However, with the new version then if the command-to-be-redefined is not currently defined then this produces errors! (The guilty commands are \includegraphics and \pgfuseimage.)

Anyway, here's the fix. Use at your own risk:

\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

(Added in edit): I made a mistake in the above code: it doesn't save the original version of the command which the beamer version of \renewcommand does. Also, due to the conflicts, I thought that actually it would be better to define a command \myrenewcommand which does the command. So the code below may be better. It's probably still nowhere near perfect - for example, I don't know if the \@star@or@long is appropriate for \renewcommands.

Anyway, here's version 2 wrapped up in a MWE:

\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}
Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751
  • Thanks! I have reported the bug: https://bitbucket.org/rivanvx/beamer/issue/119/problem-when-redefining-commands-like-emph – Ulrik Nielsen Mar 17 '11 at 13:52
  • @Ulrik: Good! Don't forget to report back if you get confirmation or anything else significant. – Andrew Stacey Mar 17 '11 at 13:56
  • @Andrew: Amongst other things, I am one of the beamer maintainers. This does look wrong to me - expect the patch to be added later today. – Joseph Wright Mar 17 '11 at 14:14
  • @Joseph: Yippee-do! I had a hazy recollection that you were somehow involved, but couldn't remember for sure. I'll be interested to see your patch and see what the most efficient way of doing this is (and why I was getting those weird things with \includegraphics as I couldn't see why they were being generated when I dug deeper). – Andrew Stacey Mar 17 '11 at 14:37
  • @Andrew: One issue with beamer is that Till's code is rather awkward to follow/alter! So the major approach is 'do not alter too much'. – Joseph Wright Mar 17 '11 at 14:39
  • @Andrew: This is a case in point - if you try to use the same definition for \renewcommand as for \newcommand all hell breaks loose! I have a fix for the matter in hand - it will be in the repo in a second, but I need Vedran to do a release (he's in charge of beamer). – Joseph Wright Mar 17 '11 at 21:11
  • @Joseph: Yes, I quickly gave up the chase of which uses of \renewcommand were legitimate and which were a bit .. dubious. – Andrew Stacey Mar 17 '11 at 21:14
  • @Andrew. One of the reasons fixes for beamer are quite slow at the moment (at least for me) is that while Till does a great job for the user, the internals are 'interesting' (try reading pgf!). – Joseph Wright Mar 17 '11 at 21:17
  • This was eventually fixed in 2017 AFAICT (this patch is for renewenvironment though): https://github.com/josephwright/beamer/commit/4c65e1663794d4172dc8cd73ade660d566c9e5e8 Debian stretch (TexLive 2016) does not contain it, but buster (TL2018) does. – stefanct Jul 09 '19 at 13:59
5

If all you want to do is have \emph embolden its text, you could do:

\let\emph\textbf

Each macro is overlay-specification aware and has the same “signature.” So just alias one for the other.

Matthew Leingang
  • 44,937
  • 14
  • 131
  • 195