The normal json format for Zed's themes is often unwieldy to edit. It is easy to forget which colors are which because you're working with hex, and when working on multiple themes, you have to copy-paste similar configuration. Overall it is a nightmare to try to experiment with different colors as you edit a theme family.
zeddy is here to help! It uses the KDL format and uses simple palette and modifier-driven approach to
allow creating themes in a much easier, less error-prone, and much more readable way. Not only that, but it also provides
a hot swap feature to make it so you can have live previews while editing.
Currently, zeddy can only be built from source and installed with cargo.
git clone https://github.com/lilyyy411/zeddy.git
cd ./zeddy
cargo install --path .A helper tool for making Zed themes using a custom KDL format that allows naming colors, reusing components, and much more
Usage: zeddy [OPTIONS] <INFILE> <COMMAND>
Commands:
generate Generates a theme family JSON file from a KDL `infile`
install Generates a theme family from a KDL `infile` and installs it. Note that this does not generate an extension from the theme: it just simply generates the JSON file
watch Watches for changes on the KDL `infile`, generates a theme from it, and installs it into `install_location`, allowing for a hot swap loop if the theme is selected
migrate Converts an existing JSON theme family into the custom KDL format. It attempts to extract all colors into a palette and names the colors at best effort
export-palette Writes the palette of a theme file to standard output in a given format
help Print this message or the help of the given subcommand(s)
Arguments:
<INFILE> The input file used to generate a new theme file
Options:
-o, --outfile <OUTFILE>
The output file for the generated file. This is not the final install location. Creates parent directories if they do not exist. Defaults to `./generated/{relative-path-to-file}.{extension}`
-i, --install-location <INSTALL_LOCATION>
The install location for the theme after generation. By default, it is automatically detected the same way that Zed does it
-h, --help
Print help
-V, --version
Print version
Using this tool to create themes requires knowledge of the typical JSON theme format, as modifiers are based on attributes in the JSON format.
If you are confused about the format, you can always take one of the default themes and pass it through the migrate subcommand
and inspect the output. Alternatively, you can check out one of my themes
Every file has a top-level meta node describing the name of the theme family and the author, corresponding to the same fields
in the typical JSON theme format.
Example:
meta {
name "Silly Themes"
author "Lilyyy411"
}Colors are one of the fundamental building blocks of theme. A color is simply a hex color string
(either #rrggbb or #rrggbbaa, #rgb is not supported) or the
name of a color in the palette along with any (or none) of the following properties
alpha(float): multiplies the alpha value of the color by the constant.lighten(float): lightens the color by the given multiplierdarken(float): darkens the color by the given multipliersaturate(float): saturates the color by the given multiplierdesaturate(float): desaturates the color by the given multiplierhue-shift(float): offsets the hue of the color by a given offset
Note that the color modifiers act in the LCH colorspace, not HSV or HSL.
For example, darken=1.0 will not always yield black and instead you would
need to desaturate the color to get the expected black. LCH has the nice property
of perceptual uniformity. If you want to hue-shift or desaturate a color in LCH,
its apparent luminosity will not change (much).
Example:
some-node "#ff00ff" alpha=0.8 // simple hex color with alpha multiplier
some-node "foobar" darken=0.1 // references the `foobar` color in the palette
// and darkens it a little bitThe palette node is used to give names to colors that can then be referred by name later in the file
Colors in the palette can reference each other as long as there are no cyclic dependencies. The
order of listing the palette colors does not matter to how they're resolved.
Example:
palette {
white "#ffffff"
grey "black" lighten=0.5
black "#000000"
transparent "totally-not-black" alpha=0.0 // multiple levels of reference are allowed
totally-not-black "black"
background = "#3A2D30ff"
}A theme node contains a node in the theme family. Each theme contains only 4 attributes: name, appearance, modifiers, and players.
appearance determines whether the theme is considered light or dark, and modifiers is a
list of modifiers, which we'll get to later. players corresponds to the players list in the styles
object of the typical JSON theme format and is used to control the colors of different users when collaborating.
A modifier-path is either a style or syntax node followed by a string representing a key
in the JSON file. A style path refers to a key in the style object
while syntax refers to a key in the style[syntax] object.
Example
style "text" // refers to `style["text"]`
syntax "text" // refers to `style["syntax"]["text"]`An action is something that can be applied to an object referred to by a modifier-path
An action consists of (currently) 4 optional attributes:
color(Color): the main color to be appliedbackground(Color): the background color of the element. Has no effect onstylepaths.font-weight(u16): the weight of the font. Has no effect onstylepaths.font-style(String): the style of the font. Has no effect onstylepaths.
A modifier consists of an action and a list of modifier paths to apply the action to.
Modifiers are applied in order of declaration from top to bottom.
Example:
modifier {
color "black" alpha=0.8
background "#B00B1350"
font-style "italic"
apply { // apply these attributes to the following:
syntax "text"
style "text" // only `color` gets applied because it is a `style` node
}
}The common node is a theme node that acts as a base for all other themes in the file. All
themes start with the content of the common theme and then can override attributes of it by explicitly providing
them.
-
Q: Why KDL? Why not something common like TOML that everyone knows
- A: KDL is less verbose and much more elegant. It's also cuddly.
-
Q: Why did you make this?
- A: Did you read the rest of the readme?