颜色未定义

颜色未定义

我想检查某种颜色是否已经定义过,请考虑下面未执行的代码。

\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}

换句话说,类似于\providecommand{...}不更新现有命令(如果存在),我需要一个宏来不是如果颜色已经定义,则重新定义颜色。

\ifx\undefined...由于逻辑检查部分不正确,上述代码会引发错误。

答案1

\definecolor{foo}{<model>}{<spec>}或之后\colorlet{foo}{<color>},新的颜色规范存储在名为

\\color@foo

(名称中带有反斜杠)。你用

\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}

在此处输入图片描述

H. Oberdiek 建议的补充

实际上xcolor已经定义了一个检查,但没有提供“公共版本”:

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

所以你可以说

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

这可能更清晰,并且不依赖于保存颜色规范的宏的内部实现。

答案2

这是一个老问题,但唯一的答案没有提到自 2.0 版(2004/07/04)以来\providecolor可用的版本。xcolor

该命令有三个参数,在这种特殊情况下,可以将其用作\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}

在此处输入图片描述

相关内容