"""Code generation script for creating the global palette constant.""" from __future__ import annotations import json import subprocess from dataclasses import asdict from pathlib import Path from typing import Any, cast from catppuccin.models import HSL, RGB, Color, Flavor, FlavorColors, Palette from example_plots import example_plots, plot_palette HEADER = '''"""Catppuccin palette definition.""" from catppuccin.models import HSL, RGB, Color, Flavor, FlavorColors, Palette''' DPI = 200 def load_palette_json() -> dict[str, Any]: """Load palette data from `./palette.json`.""" with Path("palette.json").open() as f: palette_json = cast(dict[str, Any], json.load(f)) del palette_json["version"] return palette_json def make_color(identifier: str, fields: dict[str, Any]) -> Color: """Create a Color instance from a set of fields.""" return Color( name=fields["name"], identifier=identifier, accent=fields["accent"], order=fields["order"], hex=fields["hex"], rgb=RGB(**fields["rgb"]), hsl=HSL(**fields["hsl"]), ) def make_flavor(identifier: str, fields: dict[str, Any]) -> Flavor: """Create a Flavor instance from a set of fields.""" return Flavor( name=fields["name"], identifier=identifier, order=fields["order"], dark=fields["dark"], colors=FlavorColors( **{ identifier: make_color(identifier, fields) for identifier, fields in fields["colors"].items() } ), ) def codegen() -> str: """Generate contents of `catppuccin/palette.py`.""" palette_json = load_palette_json() palette = Palette( *[ make_flavor(identifier, fields) for identifier, fields in palette_json.items() ] ) lines = [ HEADER, f"PALETTE = {palette!r}", ] return "\n".join(lines) if __name__ == "__main__": print("running codegen") palette_path = Path.cwd() / "catppuccin" / "palette.py" with palette_path.open("w", newline="\n") as f: f.write(codegen()) print("formatting with ruff") ruff_format = f"ruff format {palette_path}" subprocess.run(ruff_format.split(), check=True, stdout=subprocess.DEVNULL) print("palette.py generation complete") # Generate the matplotlib styles print("generating matplotlib styles") from catppuccin.extras.matplotlib import CATPPUCCIN_STYLE_DIRECTORY from catppuccin.palette import PALETTE template_text = ( CATPPUCCIN_STYLE_DIRECTORY / "_catppuccin_template.txt" ).read_text() for key, palette in asdict(PALETTE).items(): print(f"- {key}") text = template_text text = text.replace("", key) for color in palette["colors"]: text = text.replace( f"<{color}>", palette["colors"][color]["hex"].replace("#", ""), ) style_path = CATPPUCCIN_STYLE_DIRECTORY / f"{key}.mplstyle" with style_path.open("w", newline="\n") as f: f.write(text) print("matplotlib styles generation complete") # Generate matplotlib assets for the docs import matplotlib as mpl import matplotlib.pyplot as plt import catppuccin # This loads the styles in matplotlib # noqa: F401 print("generating matplotlib asset images") for palette_name in asdict(PALETTE): print(f"- {palette_name}") mpl.style.use(palette_name) palette_path = Path.cwd() / "assets" / palette_name palette_path.mkdir(exist_ok=True, parents=True) # Plot palette separately print(" - palette") fig = plot_palette(palette_name) fig.savefig(palette_path / "palette.png", dpi=DPI) # Plot examples for filename, plot_function in example_plots.items(): print(f" - {filename}") fig = plot_function() fig.savefig(palette_path / f"{filename}.png", dpi=DPI) plt.close() print("matplotlib asset image generation complete")