lib: let # takes in "ff0044" (no hash!) and returns { r = "ff", g = "00", b = "44" } slice-hex = hex: with builtins; { r = substring 0 2 hex; g = substring 2 2 hex; b = substring 4 2 hex; }; # takes in "44" and returns 64 drune-to-255 = drune: with builtins; (rune-to-num (substring 0 1 drune)) * 16 + (rune-to-num (substring 1 1 drune)); num-to-drune = num: "${num-to-rune (num / 16)}${num-to-rune (num - ((num / 16) * 16))}"; # takes in "D" and returns 13 # inspiration from https://github.com/bertof/nix-rice rune-to-num = rune: let dict = { "0" = 0; "1" = 1; "2" = 2; "3" = 3; "4" = 4; "5" = 5; "6" = 6; "7" = 7; "8" = 8; "9" = 9; "A" = 10; "B" = 11; "C" = 12; "D" = 13; "E" = 14; "F" = 15; }; in assert(builtins.hasAttr (lib.strings.toUpper rune) dict); builtins.getAttr (lib.strings.toUpper rune) dict; # takes in 15 and returns "F" num-to-rune = num: let num-string = builtins.toString num; dict = { "0" = "0"; "1" = "1"; "2" = "2"; "3" = "3"; "4" = "4"; "5" = "5"; "6" = "6"; "7" = "7"; "8" = "8"; "9" = "9"; "10" = "A"; "11" = "B"; "12" = "C"; "13" = "D"; "14" = "E"; "15" = "F"; }; in assert(builtins.hasAttr num-string dict); builtins.getAttr num-string dict; # Keeps num between 0 and 255 # Make sure to pass in an int not a float cap-255 = num: (if (num>255) then 255 else if (num<0) then 0 else num); nohash = hex: with builtins; assert((stringLength hex) == 7); substring 1 6 hex; in { ## USEFUL FUNCTIONS # takes in a string like "#ff0044" and returns "ff0044" symbol inherit nohash; # This takes in something like "#ff0044" and returns "255,0,64" hex-to-rgb-comma-string = hex: with (slice-hex (nohash hex)); with builtins; assert(isString hex); "${toString (drune-to-255 r)},${toString (drune-to-255 g)},${toString (drune-to-255 b)}"; # This is useful if you have a float (like a transparency value) and want a drune representation of it # So 0.0 -> "00" and 1.0 -> "FF" float-to-drune = f: with builtins; assert(isFloat f); "${num-to-rune (floor((255*f) / 16))}${num-to-rune (floor(255*f) - (floor((255*f) / 16) * 16))}"; # Takes in hex and a float. 0.5 is +50% brightness and (-0.5) is -50% brightness. # So "#ff0044": 0.3 -> "#ff0055" alter-luminace-hex = hex: amount: let color-num = with (slice-hex (nohash hex)); { r = drune-to-255 r; g = drune-to-255 g; b = drune-to-255 b; }; alter = num: (num-to-drune (cap-255 (builtins.floor ((125 * amount) + (num * (1+amount))) ))); in with color-num; "#${alter r}${alter g}${alter b}"; }