Selecting a named color from a non-current palette

In another thread I was contemplating building thumbnails representing all the palettes available. When I tried to address one of the limitations of my approach, I hit a wall: Is there a clean way to get a named color from a palette that is not the current one?

I thought it should be easy, until I realized that there is an odd sort of recursion going on in the current color retrieval process., one not trivial to override. I was wondering if anyone had a suggestion.

The current colour macro looks like approximately like this:

\define colour(name)
<$transclude tiddler={{$:/palette}} index="$name$">
  <$transclude tiddler="$:/palettes/Vanilla" index="$name$">
    <$transclude tiddler="$:/config/DefaultColourMappings/$name$"/>
  </$transclude>
</$transclude>
\end

(“Approximately” because I’ve added line-breaks and indentation for readability.)

And entries in the color palettes have one of three forms:

background: #ffffff
blockquote-bar: <<colour muted-foreground>>
button-background:

Either they are

  • references to a CSS color value (e.g. #ffffff, #cfc, rgb(51, 204, 153), or rgba(0, 200, 0, 0.7)), or they are
  • recursive references to a different value (<<color-muted-foreground>>)
  • blank, like button-background above.

The trouble for me is that the data has the recursive calls built in. I can’t write a new function that does a different recursion on the same data, because it’s already too late. The recursive call has happened before I would get a chance to deal with it, and it’s been run on the current palette, not on the version I would like.

I had two failed attempts to solve this.

First, I thought I could wrap the body of my function in a <$let> statement that set the palette to what I wanted and then reset it after I called <<colour>>. Of course this fails; the coulour macro isn’t using a variable to refer to the current palette but the text reference {{$:/palette}}. It’s possible this technique could be resurrected by changing the text value of $:/palette and then resetting afterward. I don’t really see how, as I believe this would have to be inside some user action to do this, but maybe I’m missing something. But even if I could, that would feel really wrong, to invoke a change in a fairly central tiddler just to temporarily use another value and set it back. It seems fraught.

Second, I thought I could manually do the same sort of things that the color macro is doing, by using the palette text like a data tiddler, and then manually adjusting any recursive calls to use my new version, keeping the CSS values, and for blank ones, hopping through the same Vanilla > config/DefaultColourMappings hoops done in the <<colour>> macro. I wasn’t sure I had the chops to do this all the way through, but I never got the chance because I was stopped up front by the simple fact that I can’t find a way to use a string as I would a data tiddler. Is that possible? I know I can do so with JSON strings. I can use jsonget/jsonextract to pull out values from a JSON-formatted string; can I do so with a data-tiddler formatted string (such as "a: 1\nb:2\nc:3")? Obviously, with a lot of work, I can recreate the whole data-tiddler handling bit for strings. But if I’m going to do that, then I will probably have to do that in JS, and not in wikitext, at least given my skill levels with TW and JS.

So that’s the question. Is there some simpler way to get the value of a named color from a palette that is not the current default one? Or can one of my two failed attempts be revived? Or should I – if I decide to pursue this – descend to JavaScript for this?

Hi @Scott_Sauyet this seems to work:

\define colour(name)
<$transclude tiddler=<<palette>> index=<<__name__>>>
  <$transclude tiddler="$:/palettes/Vanilla" index="$name$">
    <$transclude tiddler="$:/config/DefaultColourMappings/$name$"/>
  </$transclude>
</$transclude>
\end

<$let palette="$:/palettes/Blanca">
<<colour "primary">>
</$let>

<$let palette="$:/palettes/SolarFlare">
<<colour "primary">>
</$let>

You would need to wikify the results to get the colour as text in a variable.

1 Like

Yes it does. (primary is not a useful test, as that doesn’t invoke the recursion in these palettes, but it also works for dropdown-border, which does.)

I never considered actually overriding the colour macro itself. I guess so long as it doesn’t escape my current context, that’s not a big deal. So no global or macro tags on this.

Just out of curiosity, can you see a way to do this that doesn’t override colour? Don’t spend much time on this question; it’s not that I need it now that I have this solution, but I struggled to come up with something that didn’t reinvent the parsing of of data tiddlers, and couldn’t come up with anything. I’m just wondering if there was something useful I was missing.

I think the way that the core colour macro is hardcoded to use the current palette makes it impossible to use it in its present form. I wouldn’t consider redefining the colour macro to be a kludge: the way that macros are locally scoped and can be redefined locally is central to the operation of TiddlyWiki. I think of macros/procedures etc as the building blocks for users to make their own “Domain Specific Language” that they can evolve to suit their own data.

Thank you very much for your help. I don’t know whether I will proceed with the project that led to this question, but it’s very nice to know that I can do so if I want.