mirror of
https://github.com/catppuccin/nim.git
synced 2024-11-14 13:07:54 -06:00
feat: implement catppuccin in nim
This commit is contained in:
parent
1f1e03f873
commit
b8abe92f91
12 changed files with 609 additions and 27 deletions
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
/public/
|
||||||
|
/tools/palette-porcelain.json
|
||||||
|
|
||||||
|
/tests/**
|
||||||
|
!/tests/*.nim
|
||||||
|
!/tests/*.nims
|
43
README.md
43
README.md
|
@ -11,41 +11,30 @@
|
||||||
<a href="https://github.com/catppuccin/nim/contributors"><img src="https://img.shields.io/github/contributors/catppuccin/template?colorA=363a4f&colorB=a6da95&style=for-the-badge"></a>
|
<a href="https://github.com/catppuccin/nim/contributors"><img src="https://img.shields.io/github/contributors/catppuccin/template?colorA=363a4f&colorB=a6da95&style=for-the-badge"></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img src="https://raw.githubusercontent.com/catppuccin/catppuccin/main/assets/previews/preview.webp"/>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
## Previews
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>🌻 Latte</summary>
|
|
||||||
<img src="https://raw.githubusercontent.com/catppuccin/catppuccin/main/assets/previews/latte.webp"/>
|
|
||||||
</details>
|
|
||||||
<details>
|
|
||||||
<summary>🪴 Frappé</summary>
|
|
||||||
<img src="https://raw.githubusercontent.com/catppuccin/catppuccin/main/assets/previews/frappe.webp"/>
|
|
||||||
</details>
|
|
||||||
<details>
|
|
||||||
<summary>🌺 Macchiato</summary>
|
|
||||||
<img src="https://raw.githubusercontent.com/catppuccin/catppuccin/main/assets/previews/macchiato.webp"/>
|
|
||||||
</details>
|
|
||||||
<details>
|
|
||||||
<summary>🌿 Mocha</summary>
|
|
||||||
<img src="https://raw.githubusercontent.com/catppuccin/catppuccin/main/assets/previews/mocha.webp"/>
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
1. Clone this repository locally
|
```sh
|
||||||
2. Open the app's settings
|
nimble install https://github.com/catppuccin/nim
|
||||||
3. Select `import theme` and browse to where you cloned Catppuccin
|
```
|
||||||
4. Select it
|
|
||||||
|
The `catppuccin` nim library was designed to interface with [`treeform/chroma`](https://github.com/treeform/chroma), however it is not required for basic usage. Some of the basic color types and transformations have been ported from `chroma`
|
||||||
|
|
||||||
|
If you do wish to access `catppuccin` colors alongside `chroma` compile with `-d:inheritChroma` (see `./examples/use_chroma.nim`) to use the color types defined by `chroma`.
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
```nim
|
||||||
|
import catppuccin
|
||||||
|
|
||||||
|
echo mocha.rosewater.color().toHex()
|
||||||
|
```
|
||||||
|
|
||||||
<!-- this section is optional -->
|
<!-- this section is optional -->
|
||||||
## 🙋 FAQ
|
## 🙋 FAQ
|
||||||
|
|
||||||
- Q: **_"Where can I find the doc?"_**\
|
- Q: **_"Where can I find the doc?"_**\
|
||||||
A: Run `nim mkDocs`
|
A: Run `nimble docs`
|
||||||
|
|
||||||
## 💝 Thanks to
|
## 💝 Thanks to
|
||||||
|
|
||||||
|
|
35
catppuccin.nimble
Normal file
35
catppuccin.nimble
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import std/[os,strformat]
|
||||||
|
# Package
|
||||||
|
|
||||||
|
version = "0.1.0"
|
||||||
|
author = "Daylin Morgan"
|
||||||
|
description = "Soothing pastel theme for nim"
|
||||||
|
license = "MIT"
|
||||||
|
srcDir = "src"
|
||||||
|
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
|
||||||
|
requires "nim >= 1.6.12"
|
||||||
|
|
||||||
|
task gen, "generate src/catppuccin/palette.nim":
|
||||||
|
let paletteJson = "./tools/palette-porcelain.json"
|
||||||
|
let srcUrl = "https://raw.githubusercontent.com/catppuccin/palette/main/palette-porcelain.json"
|
||||||
|
if not fileExists(paletteJson): exec &"wget -O {paletteJson} {srcUrl}"
|
||||||
|
exec "nim r ./tools/generate.nim"
|
||||||
|
|
||||||
|
|
||||||
|
task docs, "Deploy doc html + search index to public/ directory":
|
||||||
|
let
|
||||||
|
deployDir = getCurrentDir() / "public"
|
||||||
|
pkgName = "catppuccin"
|
||||||
|
srcFile = getCurrentDir() / "src" / (pkgName & ".nim")
|
||||||
|
gitUrl = "https://github.com/daylinmorgan/catppuccin-nim"
|
||||||
|
selfExec &"doc --index:on --git.url:{gitUrl} --outdir:{deployDir} --project {srcFile}"
|
||||||
|
withDir deployDir:
|
||||||
|
mvFile(pkgName & ".html", "index.html")
|
||||||
|
for file in walkDirRec(".", {pcFile}):
|
||||||
|
# As we renamed the file, we need to rename that in hyperlinks
|
||||||
|
exec(r"sed -i -r 's|$1\.html|index.html|g' $2" % [pkgName, file])
|
||||||
|
# drop 'src/' from titles
|
||||||
|
exec(r"sed -i -r 's/<(.*)>src\//<\1>/' $1" % file)
|
2
examples/config.nims
Normal file
2
examples/config.nims
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
switch("path", "$projectDir/../src")
|
||||||
|
switch("hints", "off")
|
28
examples/term.nim
Normal file
28
examples/term.nim
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import std/[strformat]
|
||||||
|
import catppuccin
|
||||||
|
|
||||||
|
const ansiReset = "\e[0m"
|
||||||
|
|
||||||
|
proc ansi(s: string, c: ColorRGB): string =
|
||||||
|
let code = &"\e[48;2;{c.r};{c.g};{c.b}m"
|
||||||
|
result.add(code)
|
||||||
|
result.add(s)
|
||||||
|
result.add(ansiReset)
|
||||||
|
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
let flavors = @[
|
||||||
|
("latte", latte),
|
||||||
|
("frappe", frappe),
|
||||||
|
("macchiato", macchiato),
|
||||||
|
("mocha", mocha)
|
||||||
|
]
|
||||||
|
|
||||||
|
for (name, flavor) in flavors:
|
||||||
|
|
||||||
|
echo name
|
||||||
|
|
||||||
|
for name, color in flavor.fieldPairs():
|
||||||
|
write(stdout, " ".ansi(color))
|
||||||
|
|
||||||
|
write(stdout, "\n\n")
|
11
examples/use_chroma.nim
Normal file
11
examples/use_chroma.nim
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{.define: inheritChroma.}
|
||||||
|
|
||||||
|
import std/[strutils]
|
||||||
|
|
||||||
|
import catppuccin
|
||||||
|
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
echo "Mocha colors as CMYK"
|
||||||
|
for n, c in mocha.fieldPairs():
|
||||||
|
echo alignLeft(n, 9) & " -> " & $c.color().asCmyk()
|
18
src/catppuccin.nim
Normal file
18
src/catppuccin.nim
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
when not defined(inheritChroma):
|
||||||
|
import catppuccin/chroma
|
||||||
|
else:
|
||||||
|
import chroma
|
||||||
|
|
||||||
|
type
|
||||||
|
Flavor = object
|
||||||
|
rosewater*, flamingo*, pink*, mauve*, red*, maroon*, peach*, yellow*,
|
||||||
|
green*, teal*, sky*, sapphire*, blue*, lavender*, text*, subtext1*,
|
||||||
|
subtext0*, overlay2*,
|
||||||
|
overlay1*, surface2*, surface1*, surface0*, base*, mantle*,
|
||||||
|
crust*: ColorRGB
|
||||||
|
|
||||||
|
include catppuccin/palette
|
||||||
|
|
||||||
|
|
||||||
|
export mocha, latte, macchiato, frappe
|
||||||
|
export chroma
|
325
src/catppuccin/chroma.nim
Normal file
325
src/catppuccin/chroma.nim
Normal file
|
@ -0,0 +1,325 @@
|
||||||
|
import std/[hashes, math, strutils]
|
||||||
|
## standalone types/methods ported from treeform/chroma
|
||||||
|
##
|
||||||
|
|
||||||
|
# chroma/colortypes ---------------
|
||||||
|
type
|
||||||
|
Color* = object
|
||||||
|
## Main color type, float32 points
|
||||||
|
r*: float32 ## red (0-1)
|
||||||
|
g*: float32 ## green (0-1)
|
||||||
|
b*: float32 ## blue (0-1)
|
||||||
|
a*: float32 ## alpha (0-1, 0 is fully transparent)
|
||||||
|
|
||||||
|
# Color Space: rgb
|
||||||
|
ColorRGB* = object
|
||||||
|
## Color stored as 3 uint8s
|
||||||
|
r*: uint8 ## Red 0-255
|
||||||
|
g*: uint8 ## Green 0-255
|
||||||
|
b*: uint8 ## Blue 0-255
|
||||||
|
|
||||||
|
# Color Space: rgba
|
||||||
|
ColorRGBA* = object
|
||||||
|
## Color stored as 4 uint8s
|
||||||
|
r*: uint8 ## Red 0-255
|
||||||
|
g*: uint8 ## Green 0-255
|
||||||
|
b*: uint8 ## Blue 0-255
|
||||||
|
a*: uint8 ## Alpha 0-255
|
||||||
|
|
||||||
|
ColorRGBX* = object
|
||||||
|
## Premultiplied alpha RGBA color stored as 4 uint8s
|
||||||
|
r*: uint8 ## Red 0-a
|
||||||
|
g*: uint8 ## Green 0-a
|
||||||
|
b*: uint8 ## Blue 0-a
|
||||||
|
a*: uint8 ## Alpha 0-255
|
||||||
|
|
||||||
|
# Color Space: HSL
|
||||||
|
ColorHSL* = object
|
||||||
|
## HSL attempts to resemble more perceptual color models
|
||||||
|
h*: float32 ## hue 0 to 360
|
||||||
|
s*: float32 ## saturation 0 to 100
|
||||||
|
l*: float32 ## lightness 0 to 100
|
||||||
|
|
||||||
|
SomeColor* = Color|ColorRGB|ColorRGBA|ColorHSL
|
||||||
|
|
||||||
|
InvalidColor* = object of ValueError
|
||||||
|
|
||||||
|
proc color*(r, g, b: float32, a: float32 = 1.0): Color {.inline.} =
|
||||||
|
## Creates from floats like:
|
||||||
|
## * color(1,0,0) -> red
|
||||||
|
## * color(0,1,0) -> green
|
||||||
|
## * color(0,0,1) -> blue
|
||||||
|
## * color(0,0,0,1) -> opaque black
|
||||||
|
## * color(0,0,0,0) -> transparent black
|
||||||
|
Color(r: r, g: g, b: b, a: a)
|
||||||
|
|
||||||
|
proc rgb*(r, g, b: uint8): ColorRGB {.inline.} =
|
||||||
|
## Creates from uint8s like:
|
||||||
|
## * rgba(255,0,0) -> red
|
||||||
|
## * rgba(0,255,0) -> green
|
||||||
|
## * rgba(0,0,255) -> blue
|
||||||
|
ColorRGB(r: r, g: g, b: b)
|
||||||
|
|
||||||
|
proc rgba*(r, g, b, a: uint8): ColorRGBA {.inline.} =
|
||||||
|
## Creates from uint8s like:
|
||||||
|
## * rgba(255,0,0,255) -> red
|
||||||
|
## * rgba(0,255,0,255) -> green
|
||||||
|
## * rgba(0,0,255,255) -> blue
|
||||||
|
## * rgba(0,0,0,255) -> opaque black
|
||||||
|
## * rgba(0,0,0,0) -> transparent black
|
||||||
|
ColorRGBA(r: r, g: g, b: b, a: a)
|
||||||
|
|
||||||
|
proc hsl*(h, s, l: float32): ColorHSL {.inline.} =
|
||||||
|
ColorHSL(h: h, s: s, l: l)
|
||||||
|
|
||||||
|
# chroma/colortypes ---------------
|
||||||
|
|
||||||
|
# chroma/transformations ----------
|
||||||
|
|
||||||
|
proc rgba*(c: ColorRGBX): ColorRGBA {.inline.} =
|
||||||
|
## Convert a premultiplied alpha RGBA to a straight alpha RGBA.
|
||||||
|
result.r = c.r
|
||||||
|
result.g = c.g
|
||||||
|
result.b = c.b
|
||||||
|
result.a = c.a
|
||||||
|
if result.a != 0 and result.a != 255:
|
||||||
|
let multiplier = round((255 / c.a.float32) * 255).uint32
|
||||||
|
result.r = ((result.r.uint32 * multiplier + 127) div 255).uint8
|
||||||
|
result.g = ((result.g.uint32 * multiplier + 127) div 255).uint8
|
||||||
|
result.b = ((result.b.uint32 * multiplier + 127) div 255).uint8
|
||||||
|
|
||||||
|
proc rgb*(c: Color): ColorRGB {.inline.} =
|
||||||
|
## Convert Color to ColorRGB
|
||||||
|
result.r = round(c.r * 255).uint8
|
||||||
|
result.g = round(c.g * 255).uint8
|
||||||
|
result.b = round(c.b * 255).uint8
|
||||||
|
|
||||||
|
proc color*(c: ColorRGB): Color {.inline.} =
|
||||||
|
## Convert ColorRGB to Color
|
||||||
|
result.r = float32(c.r) / 255
|
||||||
|
result.g = float32(c.g) / 255
|
||||||
|
result.b = float32(c.b) / 255
|
||||||
|
result.a = 1.0
|
||||||
|
|
||||||
|
proc rgba*(c: Color): ColorRGBA {.inline.} =
|
||||||
|
## Convert Color to ColorRGBA
|
||||||
|
result.r = round(c.r * 255).uint8
|
||||||
|
result.g = round(c.g * 255).uint8
|
||||||
|
result.b = round(c.b * 255).uint8
|
||||||
|
result.a = round(c.a * 255).uint8
|
||||||
|
|
||||||
|
proc color*(c: ColorRGBA): Color {.inline.} =
|
||||||
|
## Convert ColorRGBA to Color
|
||||||
|
result.r = float32(c.r) / 255
|
||||||
|
result.g = float32(c.g) / 255
|
||||||
|
result.b = float32(c.b) / 255
|
||||||
|
result.a = float32(c.a) / 255
|
||||||
|
|
||||||
|
proc min3(a, b, c: float32): float32 {.inline.} = min(a, min(b, c))
|
||||||
|
proc max3(a, b, c: float32): float32 {.inline.} = max(a, max(b, c))
|
||||||
|
|
||||||
|
proc hsl*(c: Color): ColorHSL =
|
||||||
|
## convert Color to ColorHSL
|
||||||
|
let
|
||||||
|
min = min3(c.r, c.g, c.b)
|
||||||
|
max = max3(c.r, c.g, c.b)
|
||||||
|
delta = max - min
|
||||||
|
if max == min:
|
||||||
|
result.h = 0.0
|
||||||
|
elif c.r == max:
|
||||||
|
result.h = (c.g - c.b) / delta
|
||||||
|
elif c.g == max:
|
||||||
|
result.h = 2 + (c.b - c.r) / delta
|
||||||
|
elif c.b == max:
|
||||||
|
result.h = 4 + (c.r - c.g) / delta
|
||||||
|
|
||||||
|
result.h = min(result.h * 60, 360)
|
||||||
|
if result.h < 0:
|
||||||
|
result.h += 360
|
||||||
|
|
||||||
|
result.l = (min + max) / 2
|
||||||
|
|
||||||
|
if max == min:
|
||||||
|
result.s = 0
|
||||||
|
elif result.l <= 0.5:
|
||||||
|
result.s = delta / (max + min)
|
||||||
|
else:
|
||||||
|
result.s = delta / (2 - max - min)
|
||||||
|
|
||||||
|
result.s *= 100
|
||||||
|
result.l *= 100
|
||||||
|
|
||||||
|
func fixupColor[T: int | float32](r, g, b: var T): bool =
|
||||||
|
## performs a fixup of the given r, g, b values and returnes whether
|
||||||
|
## any of the values was modified.
|
||||||
|
## This func works on integers or floats. It is only used within the
|
||||||
|
## conversion of `Color -> ColorHCL` (on integers) and `ColorHCL -> Color`
|
||||||
|
## (on floats).
|
||||||
|
template fixC(c: untyped): untyped =
|
||||||
|
if c < T(0):
|
||||||
|
c = T(0)
|
||||||
|
result = true
|
||||||
|
when T is int:
|
||||||
|
if c > 255:
|
||||||
|
c = 255
|
||||||
|
result = true
|
||||||
|
else:
|
||||||
|
if c > 1.0:
|
||||||
|
c = 1.0
|
||||||
|
result = true
|
||||||
|
fixC(r)
|
||||||
|
fixC(g)
|
||||||
|
fixC(b)
|
||||||
|
|
||||||
|
# overload working on `var Color`. It's `discardable`, because in our usage
|
||||||
|
# here we do not really care whether a value was modified.
|
||||||
|
func fixupColor(c: var Color): bool {.inline, discardable.} =
|
||||||
|
fixupColor(c.r, c.g, c.b)
|
||||||
|
|
||||||
|
proc color*(c: ColorHSL): Color =
|
||||||
|
## convert ColorHSL to Color
|
||||||
|
let
|
||||||
|
h = c.h / 360
|
||||||
|
s = c.s / 100
|
||||||
|
l = c.l / 100
|
||||||
|
var t1, t2, t3: float32
|
||||||
|
if s == 0.0:
|
||||||
|
return color(l, l, l)
|
||||||
|
if l < 0.5:
|
||||||
|
t2 = l * (1 + s)
|
||||||
|
else:
|
||||||
|
t2 = l + s - l * s
|
||||||
|
t1 = 2 * l - t2
|
||||||
|
|
||||||
|
var rgb: array[3, float32]
|
||||||
|
for i in 0..2:
|
||||||
|
t3 = h + 1.0 / 3.0 * - (float32(i) - 1.0)
|
||||||
|
if t3 < 0:
|
||||||
|
t3 += 1
|
||||||
|
elif t3 > 1:
|
||||||
|
t3 -= 1
|
||||||
|
|
||||||
|
var val: float32
|
||||||
|
if 6 * t3 < 1:
|
||||||
|
val = t1 + (t2 - t1) * 6 * t3
|
||||||
|
elif 2 * t3 < 1:
|
||||||
|
val = t2
|
||||||
|
elif 3 * t3 < 2:
|
||||||
|
val = t1 + (t2 - t1) * (2 / 3 - t3) * 6
|
||||||
|
else:
|
||||||
|
val = t1
|
||||||
|
|
||||||
|
rgb[i] = val
|
||||||
|
result.r = rgb[0]
|
||||||
|
result.g = rgb[1]
|
||||||
|
result.b = rgb[2]
|
||||||
|
result.a = 1.0
|
||||||
|
fixupColor(result)
|
||||||
|
result
|
||||||
|
|
||||||
|
proc color*(c: Color): Color {.inline.} =
|
||||||
|
c
|
||||||
|
|
||||||
|
proc to*[T: SomeColor](c: SomeColor, toColor: typedesc[T]): T {.inline.} =
|
||||||
|
## Allows conversion of transformation of a color in any color space into any
|
||||||
|
## other color space.
|
||||||
|
when type(c) is T:
|
||||||
|
c
|
||||||
|
else:
|
||||||
|
when toColor is Color:
|
||||||
|
c.color
|
||||||
|
elif toColor is ColorRGB:
|
||||||
|
c.color.rgb
|
||||||
|
elif toColor is ColorRGBA:
|
||||||
|
c.color.rgba
|
||||||
|
elif toColor is ColorHSL:
|
||||||
|
c.color.hsl
|
||||||
|
|
||||||
|
proc asColor*(c: SomeColor): Color {.inline.} = c.to(Color)
|
||||||
|
proc asRgb*(c: SomeColor): ColorRGB {.inline.} = c.to(ColorRGB)
|
||||||
|
proc asHsl*(c: SomeColor): ColorHSL {.inline.} = c.to(ColorHSL)
|
||||||
|
|
||||||
|
# chroma/transformations ----------
|
||||||
|
|
||||||
|
# chroma --------------------------
|
||||||
|
|
||||||
|
proc toHex(a: float32): string {.inline.} = toHex(int(a))
|
||||||
|
|
||||||
|
proc `$`*(c: Color): string =
|
||||||
|
## Returns colors as "(r, g, b, a)".
|
||||||
|
"(" & $c.r & ", " & $c.g & ", " & $c.b & ", " & $c.a & ")"
|
||||||
|
|
||||||
|
func hash*(c: Color): Hash =
|
||||||
|
## Hashes a Color - used in tables.
|
||||||
|
hash((c.r, c.g, c.b, c.a))
|
||||||
|
|
||||||
|
func hash*(c: ColorRGB): Hash =
|
||||||
|
## Hashes a ColorRGB - used in tables.
|
||||||
|
hash((c.r, c.g, c.b))
|
||||||
|
|
||||||
|
func hash*(c: ColorRGBA): Hash =
|
||||||
|
## Hashes a ColorRGB - used in tables.
|
||||||
|
hash((c.r, c.g, c.b, c.a))
|
||||||
|
|
||||||
|
func hash*(c: ColorHSL): Hash =
|
||||||
|
## Hashes a ColorHSL - used in tables.
|
||||||
|
hash((c.h, c.s, c.l))
|
||||||
|
|
||||||
|
proc toHex*(c: Color): string =
|
||||||
|
## Formats color as hex (upper case):
|
||||||
|
## * red -> FF0000
|
||||||
|
## * blue -> 0000FF
|
||||||
|
## * white -> FFFFFF
|
||||||
|
template pair(n: float32): string =
|
||||||
|
toHex(n*255)[^2..^1]
|
||||||
|
pair(c.r) & pair(c.g) & pair(c.b)
|
||||||
|
|
||||||
|
proc toHexAlpha*(c: Color): string =
|
||||||
|
## Formats color as hex (upper case):
|
||||||
|
## * red -> FF0000FF
|
||||||
|
## * blue -> 0000FFFF
|
||||||
|
## * white -> FFFFFFFF
|
||||||
|
## * opaque black -> 000000FF
|
||||||
|
## * transparent black -> 00000000
|
||||||
|
template pair(n: float32): string =
|
||||||
|
toHex(n*255)[^2..^1]
|
||||||
|
pair(c.r) & pair(c.g) & pair(c.b) & pair(c.a)
|
||||||
|
|
||||||
|
proc toHtmlHex*(c: Color): string =
|
||||||
|
## Formats color as HTML hex (upper case):
|
||||||
|
## * red -> #FF0000
|
||||||
|
## * blue -> #0000FF
|
||||||
|
## * white -> #FFFFFF
|
||||||
|
'#' & c.toHex()
|
||||||
|
|
||||||
|
proc toHtmlHexTiny*(c: Color): string =
|
||||||
|
## Formats color as HTML 3 hex numbers (upper case):
|
||||||
|
## * red -> #F00
|
||||||
|
## * blue -> #00F
|
||||||
|
## * white -> #FFF
|
||||||
|
proc pair(n: float32): string =
|
||||||
|
toHex(n*15)[^1..^1]
|
||||||
|
return '#' & pair(c.r) & pair(c.g) & pair(c.b)
|
||||||
|
|
||||||
|
proc toHtmlRgb*(c: Color): string =
|
||||||
|
## Parses colors in html's rgb format:
|
||||||
|
## * red -> rgb(255, 0, 0)
|
||||||
|
## * blue -> rgb(0,0,255)
|
||||||
|
## * white -> rgb(255,255,255)
|
||||||
|
"rgb(" &
|
||||||
|
$round(c.r * 255).int & ", " &
|
||||||
|
$round(c.g * 255).int & ", " &
|
||||||
|
$round(c.b * 255).int &
|
||||||
|
")"
|
||||||
|
|
||||||
|
proc toHtmlRgba*(c: Color): string =
|
||||||
|
## Parses colors in html's rgb format:
|
||||||
|
## * red -> rgb(255, 0, 0)
|
||||||
|
## * blue -> rgb(0,0,255)
|
||||||
|
## * white -> rgb(255,255,255)
|
||||||
|
"rgba(" &
|
||||||
|
$round(c.r * 255).int & ", " &
|
||||||
|
$round(c.g * 255).int & ", " &
|
||||||
|
$round(c.b * 255).int & ", " &
|
||||||
|
$c.a &
|
||||||
|
")"
|
112
src/catppuccin/palette.nim
Normal file
112
src/catppuccin/palette.nim
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
# DO NOT EDIT this file is autogenerated by tools/generate.nim!
|
||||||
|
|
||||||
|
const
|
||||||
|
latte* = Flavor(
|
||||||
|
rosewater: ColorRGB(r: 220, g: 138, b: 120),
|
||||||
|
flamingo: ColorRGB(r: 221, g: 120, b: 120),
|
||||||
|
pink: ColorRGB(r: 234, g: 118, b: 203),
|
||||||
|
mauve: ColorRGB(r: 136, g: 57, b: 239),
|
||||||
|
red: ColorRGB(r: 210, g: 15, b: 57),
|
||||||
|
maroon: ColorRGB(r: 230, g: 69, b: 83),
|
||||||
|
peach: ColorRGB(r: 254, g: 100, b: 11),
|
||||||
|
yellow: ColorRGB(r: 223, g: 142, b: 29),
|
||||||
|
green: ColorRGB(r: 64, g: 160, b: 43),
|
||||||
|
teal: ColorRGB(r: 23, g: 146, b: 153),
|
||||||
|
sky: ColorRGB(r: 4, g: 165, b: 229),
|
||||||
|
sapphire: ColorRGB(r: 32, g: 159, b: 181),
|
||||||
|
blue: ColorRGB(r: 30, g: 102, b: 245),
|
||||||
|
lavender: ColorRGB(r: 114, g: 135, b: 253),
|
||||||
|
text: ColorRGB(r: 76, g: 79, b: 105),
|
||||||
|
subtext1: ColorRGB(r: 92, g: 95, b: 119),
|
||||||
|
subtext0: ColorRGB(r: 108, g: 111, b: 133),
|
||||||
|
overlay2: ColorRGB(r: 124, g: 127, b: 147),
|
||||||
|
overlay1: ColorRGB(r: 140, g: 143, b: 161),
|
||||||
|
surface2: ColorRGB(r: 172, g: 176, b: 190),
|
||||||
|
surface1: ColorRGB(r: 188, g: 192, b: 204),
|
||||||
|
surface0: ColorRGB(r: 204, g: 208, b: 218),
|
||||||
|
base: ColorRGB(r: 239, g: 241, b: 245),
|
||||||
|
mantle: ColorRGB(r: 230, g: 233, b: 239),
|
||||||
|
crust: ColorRGB(r: 220, g: 224, b: 232)
|
||||||
|
)
|
||||||
|
frappe* = Flavor(
|
||||||
|
rosewater: ColorRGB(r: 242, g: 213, b: 207),
|
||||||
|
flamingo: ColorRGB(r: 238, g: 190, b: 190),
|
||||||
|
pink: ColorRGB(r: 244, g: 184, b: 228),
|
||||||
|
mauve: ColorRGB(r: 202, g: 158, b: 230),
|
||||||
|
red: ColorRGB(r: 231, g: 130, b: 132),
|
||||||
|
maroon: ColorRGB(r: 234, g: 153, b: 156),
|
||||||
|
peach: ColorRGB(r: 239, g: 159, b: 118),
|
||||||
|
yellow: ColorRGB(r: 229, g: 200, b: 144),
|
||||||
|
green: ColorRGB(r: 166, g: 209, b: 137),
|
||||||
|
teal: ColorRGB(r: 129, g: 200, b: 190),
|
||||||
|
sky: ColorRGB(r: 153, g: 209, b: 219),
|
||||||
|
sapphire: ColorRGB(r: 133, g: 193, b: 220),
|
||||||
|
blue: ColorRGB(r: 140, g: 170, b: 238),
|
||||||
|
lavender: ColorRGB(r: 186, g: 187, b: 241),
|
||||||
|
text: ColorRGB(r: 198, g: 208, b: 245),
|
||||||
|
subtext1: ColorRGB(r: 181, g: 191, b: 226),
|
||||||
|
subtext0: ColorRGB(r: 165, g: 173, b: 206),
|
||||||
|
overlay2: ColorRGB(r: 148, g: 156, b: 187),
|
||||||
|
overlay1: ColorRGB(r: 131, g: 139, b: 167),
|
||||||
|
surface2: ColorRGB(r: 98, g: 104, b: 128),
|
||||||
|
surface1: ColorRGB(r: 81, g: 87, b: 109),
|
||||||
|
surface0: ColorRGB(r: 65, g: 69, b: 89),
|
||||||
|
base: ColorRGB(r: 48, g: 52, b: 70),
|
||||||
|
mantle: ColorRGB(r: 41, g: 44, b: 60),
|
||||||
|
crust: ColorRGB(r: 35, g: 38, b: 52)
|
||||||
|
)
|
||||||
|
macchiato* = Flavor(
|
||||||
|
rosewater: ColorRGB(r: 244, g: 219, b: 214),
|
||||||
|
flamingo: ColorRGB(r: 240, g: 198, b: 198),
|
||||||
|
pink: ColorRGB(r: 245, g: 189, b: 230),
|
||||||
|
mauve: ColorRGB(r: 198, g: 160, b: 246),
|
||||||
|
red: ColorRGB(r: 237, g: 135, b: 150),
|
||||||
|
maroon: ColorRGB(r: 238, g: 153, b: 160),
|
||||||
|
peach: ColorRGB(r: 245, g: 169, b: 127),
|
||||||
|
yellow: ColorRGB(r: 238, g: 212, b: 159),
|
||||||
|
green: ColorRGB(r: 166, g: 218, b: 149),
|
||||||
|
teal: ColorRGB(r: 139, g: 213, b: 202),
|
||||||
|
sky: ColorRGB(r: 145, g: 215, b: 227),
|
||||||
|
sapphire: ColorRGB(r: 125, g: 196, b: 228),
|
||||||
|
blue: ColorRGB(r: 138, g: 173, b: 244),
|
||||||
|
lavender: ColorRGB(r: 183, g: 189, b: 248),
|
||||||
|
text: ColorRGB(r: 202, g: 211, b: 245),
|
||||||
|
subtext1: ColorRGB(r: 184, g: 192, b: 224),
|
||||||
|
subtext0: ColorRGB(r: 165, g: 173, b: 203),
|
||||||
|
overlay2: ColorRGB(r: 147, g: 154, b: 183),
|
||||||
|
overlay1: ColorRGB(r: 128, g: 135, b: 162),
|
||||||
|
surface2: ColorRGB(r: 91, g: 96, b: 120),
|
||||||
|
surface1: ColorRGB(r: 73, g: 77, b: 100),
|
||||||
|
surface0: ColorRGB(r: 54, g: 58, b: 79),
|
||||||
|
base: ColorRGB(r: 36, g: 39, b: 58),
|
||||||
|
mantle: ColorRGB(r: 30, g: 32, b: 48),
|
||||||
|
crust: ColorRGB(r: 24, g: 25, b: 38)
|
||||||
|
)
|
||||||
|
mocha* = Flavor(
|
||||||
|
rosewater: ColorRGB(r: 245, g: 224, b: 220),
|
||||||
|
flamingo: ColorRGB(r: 242, g: 205, b: 205),
|
||||||
|
pink: ColorRGB(r: 245, g: 194, b: 231),
|
||||||
|
mauve: ColorRGB(r: 203, g: 166, b: 247),
|
||||||
|
red: ColorRGB(r: 243, g: 139, b: 168),
|
||||||
|
maroon: ColorRGB(r: 235, g: 160, b: 172),
|
||||||
|
peach: ColorRGB(r: 250, g: 179, b: 135),
|
||||||
|
yellow: ColorRGB(r: 249, g: 226, b: 175),
|
||||||
|
green: ColorRGB(r: 166, g: 227, b: 161),
|
||||||
|
teal: ColorRGB(r: 148, g: 226, b: 213),
|
||||||
|
sky: ColorRGB(r: 137, g: 220, b: 235),
|
||||||
|
sapphire: ColorRGB(r: 116, g: 199, b: 236),
|
||||||
|
blue: ColorRGB(r: 137, g: 180, b: 250),
|
||||||
|
lavender: ColorRGB(r: 180, g: 190, b: 254),
|
||||||
|
text: ColorRGB(r: 205, g: 214, b: 244),
|
||||||
|
subtext1: ColorRGB(r: 186, g: 194, b: 222),
|
||||||
|
subtext0: ColorRGB(r: 166, g: 173, b: 200),
|
||||||
|
overlay2: ColorRGB(r: 147, g: 153, b: 178),
|
||||||
|
overlay1: ColorRGB(r: 127, g: 132, b: 156),
|
||||||
|
surface2: ColorRGB(r: 88, g: 91, b: 112),
|
||||||
|
surface1: ColorRGB(r: 69, g: 71, b: 90),
|
||||||
|
surface0: ColorRGB(r: 49, g: 50, b: 68),
|
||||||
|
base: ColorRGB(r: 30, g: 30, b: 46),
|
||||||
|
mantle: ColorRGB(r: 24, g: 24, b: 37),
|
||||||
|
crust: ColorRGB(r: 17, g: 17, b: 27)
|
||||||
|
)
|
||||||
|
|
1
tests/config.nims
Normal file
1
tests/config.nims
Normal file
|
@ -0,0 +1 @@
|
||||||
|
switch("path", "$projectDir/../src")
|
9
tests/test1.nim
Normal file
9
tests/test1.nim
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import catppuccin
|
||||||
|
|
||||||
|
test "color":
|
||||||
|
check mocha.rosewater == ColorRGB(r: 245, g: 224, b: 220)
|
||||||
|
|
||||||
|
test "convert":
|
||||||
|
check mocha.rosewater.color().toHex() == "F5E0DC"
|
46
tools/generate.nim
Normal file
46
tools/generate.nim
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import std/[json, strformat, strutils]
|
||||||
|
|
||||||
|
|
||||||
|
type
|
||||||
|
Color = object
|
||||||
|
hex: string
|
||||||
|
rgb: array[3, int]
|
||||||
|
hsl: array[3, float]
|
||||||
|
Flavor = object
|
||||||
|
rosewater, flamingo, pink, mauve, red, maroon, peach, yellow, green, teal,
|
||||||
|
sky, sapphire, blue, lavender, text, subtext1, subtext0, overlay2,
|
||||||
|
overlay1, surface2, surface1, surface0, base, mantle, crust: Color
|
||||||
|
Palette = object
|
||||||
|
latte, frappe, macchiato, mocha: Flavor
|
||||||
|
|
||||||
|
proc createColor(c: Color, name: string): string =
|
||||||
|
result = &"""
|
||||||
|
{name}: ColorRGB(r: {c.rgb[0]}, g: {c.rgb[1]}, b: {c.rgb[2]})"""
|
||||||
|
|
||||||
|
proc createFlavor(f: Flavor, name: string): string =
|
||||||
|
var colorsDef: seq[string]
|
||||||
|
for name, color in f.fieldPairs():
|
||||||
|
colorsDef.add color.createColor(name)
|
||||||
|
|
||||||
|
result = &"""
|
||||||
|
{name}* = Flavor(
|
||||||
|
{colorsDef.join(",\n")}
|
||||||
|
)"""
|
||||||
|
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
const paletteJsonStr = slurp "./palette-porcelain.json"
|
||||||
|
const doNotEdit = "# DO NOT EDIT this file is autogenerated by tools/generate.nim!"
|
||||||
|
|
||||||
|
let palette = paletteJsonStr.parseJson().to(Palette)
|
||||||
|
var flavors: string
|
||||||
|
for name, flavor in palette.fieldPairs():
|
||||||
|
flavors &= flavor.createFlavor(name) & "\n"
|
||||||
|
|
||||||
|
let catppuccin = &"""
|
||||||
|
{doNotEdit}
|
||||||
|
|
||||||
|
const
|
||||||
|
{flavors}
|
||||||
|
"""
|
||||||
|
writeFile("./src/catppuccin/palette.nim", catppuccin)
|
Loading…
Reference in a new issue