14

I want to check whether a color has been previously defined, consider the below code which doesn't execute.

\documentclass{article}

\usepackage{xcolor}
\newcommand{\colorprovide}[2]{\ifx\undefined{#1}\colorlet{#1}{#2}\fi}

\begin{document}
    %Initial Definition
    \colorprovide{mycolor}{red}
    \textcolor{mycolor}{Test 1}

    %Will overwrite
    \colorlet{mycolor}{green}
    \textcolor{mycolor}{Test 2}

    %Should NOT overwrite as it exists
    \colorprovide{mycolor}{red}
    \textcolor{mycolor}{Test 3}
\end{document}

In other words and analogous to \providecommand{...} not renewing an existing command if it exists, I need a macro which will will NOT redefine a color if the color has already been defined.

The above code throws an error as the logical checking part \ifx\undefined... is incorrect.

19

After \definecolor{foo}{<model>}{<spec>} or \colorlet{foo}{<color>}, the new color specification is store in a macro called

\\color@foo

(with a backslash in the name). You accomplish your wish with

\documentclass{article}
\usepackage{xcolor}

\makeatletter
\newcommand{\colorprovide}[2]{%
  \@ifundefined{\string\color@#1}{\colorlet{#1}{#2}}{}}
\makeatother

\begin{document}
%Initial Definition
\colorprovide{mycolor}{red}
\textcolor{mycolor}{Test 1}

%Will overwrite
\colorlet{mycolor}{blue}
\textcolor{mycolor}{Test 2}

%Should NOT overwrite as it exists
\colorprovide{mycolor}{red}
\textcolor{mycolor}{Test 3}
\end{document}

enter image description here

Addition suggested by H. Oberdiek

Actually xcolor already defines a check, but doesn't provide a “public version”:

\def\@ifundefinedcolor#1{\@ifundefined{\string\color@#1}}

so you can say

\makeatletter
\newcommand{\colorprovide}[2]{%
  \@ifundefinedcolor{#1}{\colorlet{#1}{#2}}{}}
\makeatother

which is probably clearer and doesn't rely on the internal implementation of the macro holding the color specification.

  • Cheers. My wish is now accomplished.... – Nicholas Hamilton Jun 13 '13 at 22:06
  • 5
    Since version 2005/11/12 v2.07 package xcolor also defines \@ifundefinedcolor (with the same implementation as in your answer). – Heiko Oberdiek Jun 13 '13 at 23:35
2

This is an old question, but the only answer do not mention \providecolor that is available in xcolor since version 2.0 (2004/07/04).

This command has three parameters and in this particular case one can use it as \providecolor{<color to provide>}{named}{<existing color>}.

\documentclass[varwidth,border=7pt]{standalone}
\usepackage{xcolor}

\newcommand{\colorprovide}[2]{\providecolor{#1}{named}{#2}}

\begin{document}
  %Initial Definition
  \colorprovide{mycolor}{red}
  \textcolor{mycolor}{Test 1}

  %Will overwrite
  \colorlet{mycolor}{green}
  \textcolor{mycolor}{Test 2}

  %Should NOT overwrite as it exists
  \colorprovide{mycolor}{red}
  \textcolor{mycolor}{Test 3}
\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.