Compact and universal color macros

This is my current setup:


// color macros for math mode:

#let dd(x) = text(fill: red)[$#x$]
#let oo(x) = text(fill: orange)[$#x$]
#let yy(x) = text(fill: yellow)[$#x$]
#let nn(x) = text(fill: green)[$#x$]
#let bb(x) = text(fill: blue)[$#x$]
#let pp(x) = text(fill: purple)[$#x$]
#let kk(x) = text(fill: rgb("#ffc0cb"))[$#x$]

// example text

#text(blue)[3/2]

// example math

$
bb(3/2)
$

I would like to be able to use the shortest function possible to color any kind of body, whether it’s ordinary text or math.

Unfortunately, trying to do this uncovers hidden complications:

  1. I wasn’t able to shorten my macro to a single letter for math mode (if I did #let d(x) = text(fill: red)[$#x$] for example, $d(x)$ does not work and I would have to use #d[x] for text and #d[$x$] for math: at that point this would function regardless of mode (also outside of math mode you have to use # prefix anyway)
  2. I wasn’t able to add a condition in my code to detect which mode I’m in to avoid having to add $$ inside of [], if one wanted to use approach from complication 1 to solve the problem

These issues likely derive from my attempt to force Typst into becoming an editor built for quick notes, rather than complex typesetting.

Therefore if I ever wanted to take this further I was thinking of:
a. Making a macro outside of Typst that expands what I type into how Typst recognises it (don’t like this approach as it’s not very portable)
b. Making my own Typst package (have no idea if Typst packages offer enough flexibility to achieve anything I’ve mentioned)
c. Modify Typst source code

Any ideas?

This actually works, by using a set-rule you can do a more universal color change of text:

#let bb(it) = {
  set text(fill: blue)
  it
}

// example text
#bb[3/2]

// example math
$
  bb(3/2)
$

Actually, this is even shorter. Not sure if it has the same behaviour:

#let bb = text.with(fill: blue)

// example text
#bb[3/2]

// example math
$
  bb(3/2)
$