10

I have something like this:

\documentclass{beamer}
\newcommand<>{\mycommand}[1]{\textcolor#2{red}{#1}}

\begin{document}
 \frame{
  \mycommand{test}
 }
\end{document}

I want the command to take a default overlay specification (say, <2,4>) that will be enabled if the command is called like in the example, without overlay spec., and overwritten if the command is called with an overlay specification (say, \mycommand<1-4>).

Is this possibile?

Lep
  • 400

4 Answers4

5

This is (at least) possible by means of using TeX conditionals.

You need to test #2 for emptiness. The example below uses a temporary macro to test against \@empty whether #2 is empty. As #2 only holds a few simply characters (no TeX), you could also simply do

\ifx\\#2\

to test for an empty string (if it’s empty \ifx\\\\ will be true); instead of \\ you can also use nearly any other control sequence that doesn’t come up in #2 (e.g. \relax).

eTeX allows us to do a safe test with \detokenize:

\if\relax\detokenize{#2}\relax

There are also many packages that provide test for empty strings:

  • etoolbox: \ifstrempty{#2}{<true>}{<false>}

  • xifthen: \ifthenelse{\isempty{#2}}{<true>}{<false>}

In my example, I’m using \@firstoftwo and \@secondoftwo so that one doesn’t need to repeat the {red}{#2} part of your command. It is also preferable to use them for many other reason (see the references), especially if you want to nest \ifs.

Of course, in this simple example you don’t necessarily need this.

References

Code

\documentclass{beamer}
\makeatletter
\newcommand<>{\mycommand}[1]{%
  \def\@tempa{#2}%
  \ifx\@tempa\@empty
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
  {\textcolor<2,4>}{\textcolor#2}{red}{#1}}
\makeatother
\begin{document}
 \frame{\mycommand{test}}
\end{document}
Qrrbrbirlbel
  • 119,821
  • thanks, works. Any particular reason why you're using \expandafter\@firstoftwo and \expandafter\@secondoftwo instead of directly loading {\textcolor<2,4>{red}{#1}} and {\textcolor#2{red}{#1}}} after ifx and else? – Lep Oct 12 '13 at 15:59
  • @Lep Out of habit. In this simple case you don’t need them really. Though, I have updated my answer with a few references and an explanation. The core is: Test for empty #2. How you do that and what you do with that is basically just a question of taste, purpose and if you want to load packages. There are probably a few questions on how to test for empty strings. – Qrrbrbirlbel Oct 12 '13 at 16:47
  • thanks for the explanation. As long as a beamer based answer does not show up I will accept yours. – Lep Oct 12 '13 at 16:54
5
\documentclass{beamer} 
\newcommand<>\mycommand[1]{%
  \ifx\relax#2\relax \textcolor<2,4>{red}{#1}% #2 is empty
  \else              \textcolor#2{red}{#1}%
  \fi}
\begin{document}

 \frame{\mycommand{test}}
 \frame{\mycommand<1>{test}}

\end{document}
2

With xparse's optional delimiter D-specification:

o A standard LaTeX optional argument, surrounded with square brackets, which will supply the special -NoValue- marker if not given (as described later).

d Given as d<token1><token2>, an optional argument which is delimited by <token1> and <token2>. As with o, if no value is given the special marker -NoValue- is returned.

D Given as D<token1><token2>{<default>}, it is as for d, but returns <default> if no value is given. Internally, the o, d and O types are short-cuts to an appropriated constructed D type argument.

\documentclass{beamer}

% If you don't have an up-to-date TeX distribution, include xparse manually % \usepackage{xparse} \NewDocumentCommand{\mycommand}{ D<>{2,4} m }{% \textcolor<#1>{red}{#2}% }

\begin{document}

\begin{frame} \mycommand{test} \end{frame}

\end{document}

Werner
  • 603,163
1

Note: Werner's answer is better than mine.


I was able to achieve this with xparse:

\NewDocumentCommand{\mycommand}{O{<2,4>} m}{\textcolor#1{red}{#2}}

One problem with this solution is having to use [ ]'s to wrap the overlay specification around like so:

\mycommand[<1-4>]{test}

Complete code:

\documentclass{beamer}
\usepackage{xparse}

\NewDocumentCommand{\mycommand}{O{<2,4>} m}{\textcolor#1{red}{#2}}

\begin{document} \frame{ \mycommand{test} \mycommand[<1-4>]{test} } \end{document}

Leone
  • 576