Logo
Catppuccin Whiskers

  Whiskers is a port creation helper tool that is custom-built for Catppuccin, allowing developers to define template files which the palette can be injected into. > [!IMPORTANT] > This repository has been migrated from > [catppuccin/toolbox](https://github.com/catppuccin/toolbox/tree/main/whiskers). To view releases > prior to [v2.3.0](https://github.com/catppuccin/whiskers/releases/tag/v2.3.0), > see the [releases from catppuccin/toolbox](https://github.com/catppuccin/toolbox/releases?q=whiskers&expanded=true). ## Installation You can install Whiskers using one of the methods below: | Installation Method | Instructions | | ------------------------------------- | ------------------------------------------------------------------------------------------------------- | | crates.io | `cargo install catppuccin-whiskers` | | Source | `cargo install --git https://github.com/catppuccin/whiskers catppuccin-whiskers` | | Homebrew | `brew install catppuccin/tap/whiskers` | | Nix | `nix profile install github:catppuccin/whiskers`
`nix run github:catppuccin/whiskers -- ` | | Binaries
(Windows, MacOS & Linux) | Available from the [latest GitHub release](https://github.com/catppuccin/whiskers/releases?q=whiskers). | ## Usage ```console $ whiskers --help Soothing port creation tool for the high-spirited! Usage: whiskers [OPTIONS] [TEMPLATE] Arguments: [TEMPLATE] Path to the template file, or - for stdin Options: -f, --flavor Render a single flavor instead of all four [possible values: latte, frappe, macchiato, mocha] --color-overrides Set color overrides --overrides Set frontmatter overrides --check [] Instead of creating an output, check it against an example In single-output mode, a path to the example file must be provided. In multi-output mode, no path is required and, if one is provided, it will be ignored. --dry-run Dry run, don't write anything to disk --list-functions List all Tera filters and functions --list-flavors List the Catppuccin flavors --list-accents List the Catppuccin accent colors -o, --output-format Output format of --list-functions [default: json] [possible values: json, yaml, markdown, markdown-table, plain] -h, --help Print help (see a summary with '-h') -V, --version Print version ``` ## Template Please familiarize yourself with [Tera](https://keats.github.io/tera/), which is the templating engine used in Whiskers. ### Naming Convention Whiskers imposes no restrictions on template names. However, we recommend you use one the following options: - `.tera` in the repo root for ports that only need one template. - For example the [lazygit](https://github.com/catppuccin/lazygit) port uses [`lazygit.tera`](https://github.com/catppuccin/lazygit/blob/main/lazygit.tera) - `templates/.tera` especially for ports that have multiple templates. - For example, a port that generates files called `ui.cfg` and `palette.cfg` could use `templates/ui.tera` and `templates/palette.tera` respectively. These conventions exist to make it easier for contributors to find templates and to give code editors a hint about the correct file type. ### Context Variables The following variables are available for use in your templates: #### Single-Flavor Mode | Variable | Description | | -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | | `flavor` ([`Flavor`](#flavor)) | The flavor being templated. | | `rosewater`, `flamingo`, `pink`, [etc.](https://github.com/catppuccin/catppuccin#-palette) ([`Color`](#color)) | All colors of the flavor being templated. | | Any Frontmatter | All frontmatter variables as described in the [Frontmatter](#Frontmatter) section. | #### Multi-Flavor Mode | Variable | Description | | --------------------------------------------- | ---------------------------------------------------------------------------------- | | `flavors` (Map\) | An array containing all of the named flavors, with every other context variable. | | Any Frontmatter | All frontmatter variables as described in the [Frontmatter](#Frontmatter) section. | #### Types These types are designed to closely match the [palette.json](https://github.com/catppuccin/palette/blob/main/palette.json). ##### Flavor | Field | Type | Description | Examples | | ------------ | -------------------- | ------------------------------------------------------ | ----------------------------------------------- | | `name` | `String` | The name of the flavor. | `"Latte"`, `"FrappΓ©"`, `"Macchiato"`, `"Mocha"` | | `identifier` | `String` | The identifier of the flavor. | `"latte"`, `"frappe"`, `"macchiato"`, `"mocha"` | | `emoji` | `char` | Emoji associated with the flavor. | `'🌻'`, `'πŸͺ΄'`, `'🌺'`, `'🌿'` | | `order` | `u32` | Order of the flavor in the palette spec. | `0` to `3` | | `dark` | `bool` | Whether the flavor is dark. | `false` for Latte, `true` for others | | `light` | `bool` | Whether the flavor is light. | `true` for Latte, `false` for others | | `colors` | `Map` | A map of color identifiers to their respective values. | | ##### Color | Field | Type | Description | Examples | | ------------ | -------- | ----------------------------------------------- | -------------------------------------- | | `name` | `String` | The name of the color. | `"Rosewater"`, `"Surface 0"`, `"Base"` | | `identifier` | `String` | The identifier of the color. | `"rosewater"`, `"surface0"`, `"base"` | | `order` | `u32` | Order of the color in the palette spec. | `0` to `25` | | `accent` | `bool` | Whether the color is an accent color. | | | `hex` | `String` | The color in hexadecimal format. | `"1e1e2e"` | | `int24` | `u32` | Big-endian 24-bit color in RGB order. | `1973806` | | `uint32` | `u32` | Big-endian unsigned 32-bit color in ARGB order. | `4280163886` | | `sint32` | `i32` | Big-endian signed 32-bit color in ARGB order. | `-14803410` | | `rgb` | `RGB` | The color in RGB format. | | | `hsl` | `HSL` | The color in HSL format. | | | `opacity` | `u8` | The opacity of the color. | `0` to `255` | ##### RGB | Field | Type | Description | | ----- | ---- | ------------------------------- | | `r` | `u8` | The red channel of the color. | | `g` | `u8` | The green channel of the color. | | `b` | `u8` | The blue channel of the color. | ##### HSL | Field | Type | Description | | ----- | ----- | ---------------------------- | | `h` | `u16` | The hue of the color. | | `s` | `u8` | The saturation of the color. | | `l` | `u8` | The lightness of the color. | ### Functions | Name | Description | Examples | | ----------- | ------------------------------------------------------------------------------ | --------------------------------------------------- | | `if` | Return one value if a condition is true, and another if it's false | `if(cond=true, t=1, f=0)` β‡’ `1` | | `object` | Create an object from the input | `object(a=1, b=2)` β‡’ `{a: 1, b: 2}` | | `css_rgb` | Convert a color to an RGB CSS string | `css_rgb(color=red)` β‡’ `rgb(210, 15, 57)` | | `css_rgba` | Convert a color to an RGBA CSS string | `css_rgba(color=red)` β‡’ `rgba(210, 15, 57, 1.00)` | | `css_hsl` | Convert a color to an HSL CSS string | `css_hsl(color=red)` β‡’ `hsl(347, 87%, 44%)` | | `css_hsla` | Convert a color to an HSLA CSS string | `css_hsla(color=red)` β‡’ `hsla(347, 87%, 44%, 1.00)` | | `read_file` | Read and include the contents of a file, path is relative to the template file | `read_file(path="abc.txt")` β‡’ `abc` | ### Filters | Name | Description | Examples | | ---------------- | ---------------------------------------------------------------- | ------------------------------------------------ | | `add` | Add a value to a color | `red \| add(hue=30)` β‡’ `#ff6666` | | `sub` | Subtract a value from a color | `red \| sub(hue=30)` β‡’ `#d30f9b` | | `mod` | Modify a color | `red \| mod(lightness=80)` β‡’ `#f8a0b3` | | `mix` | Mix two colors together | `red \| mix(color=base, amount=0.5)` β‡’ `#e08097` | | `urlencode_lzma` | Serialize an object into a URL-safe string with LZMA compression | `red \| urlencode_lzma` β‡’ `#ff6666` | | `trunc` | Truncate a number to a certain number of places | `1.123456 \| trunc(places=3)` β‡’ `1.123` | | `css_rgb` | Convert a color to an RGB CSS string | `red \| css_rgb` β‡’ `rgb(210, 15, 57)` | | `css_rgba` | Convert a color to an RGBA CSS string | `red \| css_rgba` β‡’ `rgba(210, 15, 57, 1.00)` | | `css_hsl` | Convert a color to an HSL CSS string | `red \| css_hsl` β‡’ `hsl(347, 87%, 44%)` | | `css_hsla` | Convert a color to an HSLA CSS string | `red \| css_hsla` β‡’ `hsla(347, 87%, 44%, 1.00)` | > [!NOTE] > You also have access to all of Tera's own built-in filters and functions. > See [the Tera documentation](https://keats.github.io/tera/docs/#built-ins) for > more information. ## Frontmatter Whiskers templates may include a frontmatter section at the top of the file. The frontmatter is a YAML block that contains metadata about the template. If present, the frontmatter section must be the first thing in the file and must take the form of valid YAML set between triple-dashed lines. ### Template Version The most important frontmatter key is the Whiskers version. This key allows Whiskers to ensure that it is rendering a template that it can understand. Example: ```yaml --- whiskers: version: "2.0.0" --- ... standard template content goes here ... ``` If the version key is not present, Whiskers will display a warning and attempt to render the template anyway. However, it is recommended to always include the version key to ensure compatibility with future versions of Whiskers. ### Hex Format The format used for rendering colors in hexadecimal can be customised with the `hex_format` frontmatter variable. This string is rendered as a Tera template with the following context variables: - `r`, `g`, `b`, `a`: The red, green, blue, and alpha channels of the color as lowercase 2-digit hexadecimal strings. - `R`, `G`, `B`, `A`: As above, but uppercase. - `z`: The same as `a` if the color is not fully opaque, otherwise an empty string. - `Z`: As above, but uppercase. The default value of `hex_format` is `{{r}}{{g}}{{b}}{{z}}`. Example: ``` --- whiskers: version: "2.0.0" hex_format: "0x{{B}}{{G}}{{R}}{{A}}" --- {{red.hex}} ``` Running `whiskers example.tera -f mocha` produces the following output: `0xA88BF3FF` ### Frontmatter Variables You can also include additional context variables in the templating process by adding them to your template's frontmatter. As a simple example, given the following template (`example.tera`): ```yaml --- app: "Pepperjack" author: "winston" --- # Catppuccin for {{app}} # by {{author}} bg = '{{base.hex}}' fg = '{{text.hex}}' ``` Running `whiskers example.tera -f mocha` produces the following output: ```yaml # Catppuccin for Pepperjack # by winston bg = '1e1e2e' fg = 'cdd6f4' ``` A common use of frontmatter is setting an accent color for the theme: ``` --- accent: "mauve" --- {% set darkGreen = green | sub(lightness=30) %} bg = "#{{base.hex}}" fg = "#{{text.hex}}" border = "#{{flavor.colors[accent].hex}}" diffAddFg = "#{{green.hex}}" diffAddBg = "#{{darkGreen.hex}}" ``` Rendering the above template produces the following output: ```ini bg = "#1e1e2e" fg = "#cdd6f4" border = "#cba6f7" diffaddfg = "#a6e3a1" diffaddbg = "#40b436" ``` ## Overrides Frontmatter overrides can also be specified through the cli via the `--overrides` flag, taking in a JSON string resembling the frontmatter. This is particularly useful with build scripts to automatically generate files for each accent: `example.tera` ```yaml --- accent: "mauve" --- theme: accent: "{{flavor.colors[accent].hex}}" ``` When running `whiskers example.tera -f latte --overrides '{"accent": "pink"}'`, the `accent` will be overridden to pink. ## Color Overrides Color overrides can be specified through the cli via the `--color-overrides` flag. This flag takes a JSON string like the following: ```json { "all": { "text": "ff0000" }, "mocha": { "base": "000000", "mantle": "010101", "crust": "020202" } } ``` Passing these overrides would set the `text` color to bright red for all flavors, and the `base`, `mantle`, and `crust` colors to black/near-black for Mocha. ## Single-Flavor Mode Running Whiskers with the `--flavor/-f` flag causes it to run in single-flavor mode. This means the chosen flavor is placed into the template context as `flavor` and, for convenience, all of its colors are also placed into the context as their respective identifiers (`red`, `surface0`, et cetera.) ## Multi-Flavor Mode Running Whiskers without the `--flavor/-f` flag causes it to run in multi-flavor mode. In this mode, all flavors are placed into the template context as a map of flavor identifiers to their respective [`Flavor`](#flavor) objects. This map can be iterated like so: ``` {% for id, flavor in flavors %} {{id}} is one of "latte", "frappe", "macchiato", or "mocha". {{flavor}} is an object containing the flavor's properties and colors. {% endfor %} ``` Please see the [examples/single-file](examples/single-file) directory for more concrete examples on how it can be used. ## Template Matrix Whiskers can render multiple outputs from a single template using a matrix set in the frontmatter. This can be useful for generating one output per flavor per accent color, for example. In this mode Whiskers will render directly into a set of files as specified by the `filename` key in the frontmatter. This can be disabled with the `--dry-run` flag, in which case Whiskers will render the templates but not actually write them anywhere. The matrix is defined as a list of iterables. Whiskers will generate a file for each combination of the iterables in the matrix. Some of the iterables in the matrix can be strings without any values provided. In this case, Whiskers will treat it as a "magic iterable", which is an iterable that Whiskers can automatically generate values for before rendering the template. The following magic iterables are supported: - `flavor`: latte, frappe, macchiato, mocha - `accent`: rosewater, flamingo, pink, mauve, red, maroon, peach, yellow, green, teal, sky, sapphire, blue, lavender Example: ``` --- whiskers: version: 2.0.0 matrix: - variant: ["normal", "no-italics"] - flavor - accent filename: "catppuccin-{{flavor.identifier}}-{{accent}}-{{variant}}.ini" --- # Catppuccin {{flavor.name}}{% if variant == "no-italics" %} (no italics){% endif %} [theme] {{accent}}: #{{flavor.colors[accent].hex}} ``` Running `whiskers template.tera` will generate the following files: ``` catppuccin-latte-rosewater-normal.ini catppuccin-latte-rosewater-no-italics.ini catppuccin-latte-flamingo-normal.ini catppuccin-latte-flamingo-no-italics.ini ... catppuccin-frappe-rosewater-normal.ini catppuccin-frappe-rosewater-no-italics.ini ``` ... and so on for every combination of flavor, accent, and variant. Notice that the filenames are generated by rendering the `filename` key in the frontmatter for each combination of the matrix iterables. ## Check Mode You can use Whiskers as a linter with _check mode_. To do so, set the `--check` option. Whiskers will render your template as per usual, but then instead of printing the result it will check it against the expected output and fail with exit code 1 if they differ. This is especially useful in CI pipelines to ensure that the generated files are not changed without a corresponding change to the templates. In single-flavor mode, you must provide the path to the expected output file as an argument to the `--check` option. In multi-flavor mode, the path is unnecessary and will be ignored. Whiskers will diff the output against the check file using the program set in the `DIFFTOOL` environment variable, falling back to `diff` if it's not set. The command will be invoked as `$DIFFTOOL `. ```console $ whiskers theme.tera latte --check themes/latte.cfg (no output, exit code 0) $ whiskers theme.tera latte --check themes/latte.cfg Templating would result in changes. 4c4 < accent is #ea76cb --- > accent is #40a02b (exit code 1) ``` ## Editor Support Tera's syntax is not natively supported by most editors. Some editors have extensions available that provide syntax highlighting and other features for Tera templates. In the case that your editor does not have a viable extension available, you can try using a Jinja extension instead. While not an exact match, Tera's syntax is similar enough to Jinja's that it can be used quite well in most cases. For Visual Studio Code users we recommend the [Better Jinja](https://marketplace.visualstudio.com/items?itemName=samuelcolvin.jinjahtml) extension. ## Further Reading - See the [examples](examples) directory which further showcase the utilities and power of whiskers. - See the RFC, [CAT-0003-Whiskers](https://github.com/catppuccin/community/blob/main/rfc/CAT-0003-Whiskers.md), to understand the motivation behind creating whiskers.  

Copyright © 2023-present Catppuccin Org