latex3 / xcolor

Driver-independent color extensions for LaTeX and pdfLaTeX
LaTeX Project Public License v1.3c
28 stars 5 forks source link

Use colors without defining them beforehand #13

Closed tobiasBora closed 11 months ago

tobiasBora commented 2 years ago

As I explained in this question, using definecolor everytime I want to use a new color can be sometimes cumbersome. Notably, when the color is supposed to be used only once, it does not make sense to create a named color: it is not only time consuming, but it can also lead to strange bugs, for instance if multiple parts of the file redefine the same color by mistake.

As of today, it is possible to use something like \textcolor[HTML]{a65dbd}{...} but it does not generalize to other packages easily, each package need a custom code to accept this optional argument. For instance, it is not possible to do \tikz \node[draw=[HTML]{a65dbd},text=[HTML]{00aa00}]{...}, and people are struggling to find a syntax to add it to existing packages like tabularray https://github.com/lvjr/tabularray/issues/106.

On the other hand, xcolor already accepts pretty involved colors with arguments (which work for any package based on xcolor like tikz or tabularray...), like red!50!white!30.

Would it be possible to follow the approach used in red!50!white!30 to provide a way to use colors without defining them beforehand? Something like model(parameters), such as HTML(00aa52) or rgb(0.1,0.5,0.9)? If it's too hard to get a generic approach, at least could you provide this syntax for the html model as it is used pretty much in all applications?

josephwright commented 2 years ago

Isn't that already in xcolor as an 'extended' expression?

tobiasBora commented 2 years ago

Hum, I don't know, but I was not able to make it work:

\documentclass{article}
\usepackage{xcolor}
\usepackage{tikz}
\begin{document}
\textcolor{HTML:a65dbd,1}{This is NOT working}
\tikz \node[draw={HTML:a65dbd,1}]{This is NOT working};
\end{document}

I get an error ERROR: Package xcolor Error: Undefined color a65dbd.. Maybe you could provide an example where this compiles?

josephwright commented 2 years ago

Hmm. checking I was wrong: the extended models won't help. The thing here is, I suspect, that for xcolor itself the use case is already covered by \textcolor[model]{values}. The fact that some packages using xcolor don't provide an easy way to get to that input form isn't something we can fix from 'here'.

josephwright commented 2 years ago

In particular, for TikZ the docs say

The ⟨color name⟩ is the name of a previously defined color. For LATEX users, this is just a normal “LATEX-color” and the xcolor extensions are allowed.

u-fischer commented 2 years ago

Sorry but it would complicate the parsing quite a lot if something like \color{HTML(00aa52)} would have to be interpreted as \color[HTML]{00aa52} (and it would be error prone).

tobiasBora commented 2 years ago

I think it is a bit sad to ask to each program using xcolor to implement it on his side because most of the time they will either forget to implement it, or use a syntax which will differ between programs.

Concerning the parsing, I guess you know better than me what you are talking about, but answers like this one suggests that we can easily define a simpler parser that can recognize something like HTML+00aa52 (if this syntax is easier to parse than HTML(...), I'm fine with that). Or to reduce errors, we could define a syntax like <HTML>00aa52, this way the parser would only need to check if the expression is starting with <, then cut the expression after the first > and pass the first and second part to \color. Or maybe I'm missing something?

u-fischer commented 2 years ago

pass the first and second part to \color

Why do you think that the parts need only to be passed to \color? Your problem is with colors given in key-val-arguments and you actually don't know what the package really does with the color value. hyperref doesn't use \color for link borders, coloring links use a different syntax and method. And tikz doesn't issue a simple \color either as it has to handle stroke and fill colors and does a lot of low-level manipulations.

blefloch commented 2 years ago

Even if adding a syntax to xcolor might not make it available in all other packages, it would still help standardize how the color model should be supported.

Perhaps \color{[HTML]00aa52}?

davidcarlisle commented 2 years ago

Even if adding a syntax to xcolor might not make it available in all other packages, it would still help standardize how the color model should be supported.

Perhaps \color{[HTML]00aa52}?

from the point of view of color and xcolor (and l3color and luacolor etc) that's not really an improvement, just adding a somewhat strained syntax duplicating \color[HTML]{00aa52}. For other interfaces, forcing the already complicated color mix syntax to support inline color models doesn't really seems that natural, eg I'd rather see

\whatever[color-model=HTML, color=00aa52]{zzz}

than

\whatever[color={[HTML]00aa52}]{zzz}

blefloch commented 2 years ago

I'd rather see |\whatever[color-model=HTML, color=00aa52]{zzz}| than |\whatever[color={[HTML]00aa52}]{zzz}|

But then if I define a shortcut

\newcommand\mywhat[1][] {\whatever[color-model=HTML, color=00aa52, font=bold, #1]}

and somewhere I want to override the color with

\colorlet{decaff}{brown!50} \mywhat[color=decaff]

then accidentally my overriding color is interpreted as HTML instead of a named color.

davidcarlisle commented 2 years ago

well perhaps but that's just user error: if you define a command that takes html colors only then you need to pass that in, no different to any other command you define that may have syntax requirements. If the model isn't fixed as HTML you should expose that as an argument of the command being defined.

eg9 commented 2 years ago

Cooperation with all other packages that support color would probably be a nightmare.

But in my opinion, this thread starts from a wrong point of view. Colors should be defined by name before their usage, possibly in a special section of the preamble.

Coloring documents is not using whatever color pops out of mind at a given moment. They should be carefully chosen and weighed to mix with each other and in a small number. There's no such thing as “a color that's used only once” in a well formed document. Maybe in a small example one would not bother with defining names that carry some semantic about their usage.

And for a TikZ application, one can just do \definecolor{tempcolor1}[model]{<spec>} in the tikzpicture environment and use draw=tempcolor1. With some advantages. One can define the temporary colors with different models according to some switch, without changing the picture code.

It's possible that a brand new syntax might catch on and be supported in the future by packages such as TikZ/PGF, but I don't really expect it.

lvjr commented 2 years ago

In my opinion, the best and easiest solution is to provide only some hook to users and other packages. Then any one could write

\AddToHook{xcolor/undefined}{
  Do something you need
}
u-fischer commented 2 years ago

For other interfaces, forcing the already complicated color mix syntax to support inline color models doesn't really seems that natural

color={[HTML]{00aa52}} or linkbordercolor=[rgb]{1,0,0} looks a bit strained but it is the syntax supported by hyperref (hycolor) and nicematrix since quite a long time and it follows the syntax of the various color commands.

, eg I'd rather see

\whatever[color-model=HTML, color=00aa52]{zzz}

That would introduce an order requirement into the key list and you would have to handle

`\whatever[color-model=HTML, fillcolor=00aa52, color-model=named, strokecolor=red,color-model=rgb,topcolor={1,0.5,1}]{zzz}`

I don't think that this is worth it. As @eg9 wrote in most cases one should define a color first anyway, and in the cases where using values can make sense like in a \hypersetup the existing syntax is imho ok.

akloeckner commented 2 years ago

While investigating #15, I browsed through the issues, found this one and thought: Hey, maybe the workaround might work for your use case, too...

I think, some colors can be given as extended expressions, e.g., TikZ seems to accept something like the following:

\documentclass{article}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
    \draw[fill={rgb:red,100;green,50;blue,20}]      (5.0,0) rectangle ++(.4,.4);
\end{tikzpicture}
\end{document}

That might be somewhat lengthy, but could maybe be used to specify colors on-the-fly...

u-fischer commented 11 months ago

I'm closing this as it is not an xcolor issue. xcolor allows to use colors "on-the-fly" with the mentioned syntax \color[rgb]{1,0,0}. Imho this is also a sensible syntax for keyval options (and hyperref supports e.g. linkcolor=[rgb]{0,1,0}) but it is up to packages like tikz to decide if they want to support it or not.