Introduction
If comming from v2, please check v3 breaking changes.
wallust is a command line tool for creating 16 color palettes, since it was the original intent of pywal, the tool that inspired the creation of wallust.
Features
- Includes man pages and completions!
- Sets terminal colors on all (or the current,
-u
) active terminals:- Windows: Adds a
color scheme for the windows terminal
by updating
settings.json
on Windows Terminal, to enable this scheme for the first time you will have to selected it manually - *NIX: ASCII escape sequences:
/dev/pts/
on Linuxps
to search active terminals on OpenBSD
- MacOS: iTerm2 sequences,
/dev/ttys00
on MacOS
- Windows: Adds a
color scheme for the windows terminal
by updating
- Cache scheme palettes, overwritten by
-w
:- Linux:
$XDG_CACHE_HOME
or$HOME/.cache
- MacOs:
$HOME/Library/Caches
- Windows:
{FOLDERID_LocalAppData}
- Linux:
- Read pywal/terminal-sexy colorschemes with
wallust cs
. - Built-in themes with
wallust theme
(compile time feature). - Optional Configuration file,
wallust.toml
:- wallust checks for
~/.config/wallust/wallust.toml
for the config file, if not found it will use default implementations. - Configuration variables are avaliable as cli flags.
- Optional templating with a subset of Jinja2 or pywal syntax if selected.
- Configurable methods for backends, colorspaces, palettes and threshold.
- OS dependant path:
- Linux:
$XDG_CONFIG_HOME
or$HOME/.config
- MacOs:
$HOME/Library/Application Support
- Windows:
{FOLDERID_RoamingAppData}
- Linux:
- wallust checks for
Methods | Description |
---|---|
Backends | How to extract the colors from the image. (e.g pywal uses convert) |
ColorSpace | Get the most prominent color, and sort them according to the Palette , configurable by a threshold |
Palette | Makes a scheme palette with the gathered colors, (e.g. sets light background) |
Installation
wallust can run on Linux, BSDs, MacOS and Windows.
- For Linux, first check if your distro already has it packaged.
- You can also check out Building from source, to compile the program.
Binary packages
Go to the releases
and download the tar.gz
file.
- you have a binary for musl, so it works for most *nix platforms, or
- a
.exe
for Windows users.
tar -xf wallust-TARGET.tar.gz
Distribution Packages
Arch User Repository (AUR)
Using an Arch based distro, you can use the wallust or wallust-git packages.
wallust
fetches the latest stable version fromstatic.crates.io
. Prefer this package.wallust-git
fetches the latest unstable version from themaster
.
Either can be installed on an Arch based distro with the following commands:
git clone https://aur.archlinux.org/wallust.git # Or wallust-git.git
cd wallust # or wallust-git
makepkg -si
NetBSD
If you are using NetBSD, a native package is available from the official repositories. To install it, simply run:
pkgin install wallust
Nix
If you are using Nix, a native package is available.
Install it for your profile:
nix-env -iA nixos.wallust # change `nixos` for `nixpkgs`, if on a non-NixOS system
Try it with nix-shell
nix-shell -p wallust
Add the following Nix code to your NixOS Configuration, usually located in /etc/nixos/configuration.nix
environment.systemPackages = [
pkgs.wallust
];
If you are using flakes, you can directly use this repo to get the latest release:
First add this to your flake.nix
inputs.wallust.url = "git+https://codeberg.org/explosion-mental/wallust?ref=master";
Then in your configuration.nix
environment.systemPackages = [
inputs.wallust.packages.${pkgs.system}.wallust
];
You can change ref to a tag version to get a stable release.
Building from source
Migration guide to v3
The last stable backwards compatible version is 2.10. V3 builds have the following breaking changes:
Cli
The usual, and shorter, wallust image.png
, is deprecated.
Instead, you should use wallust run image.png
.
Regarding cli flags: --filter
and -f
will be replaced by --palette
and -p
, respectively.
wallust.toml
You can update your configuration file syntax with: wallust migrate
Old syntax:
[[entry]]
template = "zathurarc"
target = "~/.config/zathura/zathurarc"
[[entry]]
template = "dunst"
target = "~/.config/dunst/dunstrc"
...
New syntax:
[templates]
# usual dotted fields
dunst.template = 'dunstrc.monitor'
dunst.target = '~/.config/dunst/dunstrc'
# or inline
zathura = { template = 'zathura', target = '~/.config/zathura/zathurarc' }
# templated alias to src and target to dst
res.src = 'xres'
res.dst = '~/.config/Xresources'
res.pywal = true #enable pywal syntax
# inline with aliases, even more shorter!
glava = { src = 'glava/main.glsl', dst = '~/.config/glava/rc.glsl' }
# inline with pywal
test = { template = 'test.json', dst = '~/.config/complicated.json', pywal = true }
# directory usecase, all my pywal templates go here.
dir.template = "templates/"
dir.target = "~/.cache/wal/"
dir.pywal = true
This is a more shorter and simpler way. Inside the templates
header, you can
use the template
and target
attributes, also alias as src
and dst
respectively.
You can now declare directories as templates and targets non-recursively.
Deprecation of new_engine
The new_engine
optional value has been stablished as the default engine and
is no longer a valid variable. Now, if you want to enable pywal like syntax
(meaning it's disabled by default), you do so by declaring pywal = true
.
Rename filter
-> palette
Just like with the cli, filter to palette rename has also affected the config:
Old syntax:
filter = dark16
New syntax:
palette = dark16
Templates
Following the name changes, variable name changes also have been applied:
{{filter}}
-> {{palette}}
.
Or, if pywal
enabled, {filter}
-> {palette}
.
Variables has been reduced to the ones with no .method
syntax like. This is
because there has been included a runtime that can interpret filters. For example:
{{color0.rgb}}
is now written like:
{{color0 | rgb}}
In these lines, escaping {{
and }}
has also changed, being avaliable literals as variables:
{{{{}}{{}}}}
is now written like:
{{ "{{}}" }}
To learn more about the new template syntax please read the man page man wallust
.
Parameters
This is how to modify behaviour in wallust. Here you can find an explanation behind concepts that the program utilizes.
Alpha
Alpha value for templating (default: 100).
This value doesn't do anything other than represent the variable called alpha
in templates. This is simply a left over of niche use cases.
To edit this value:
- Config file:
alpha = 50
- Cli:
wallust run image.png --alpha 50
Backend
Allows you to choose which method to use in order to parse the image.
Backends | Description |
---|---|
Full | Read and return the whole image pixels (more precision, slower) |
Resized | Resizes the image before parsing, mantaining it's aspect ratio |
Wal | Uses image magick convert to generate the colors, like pywal |
Thumb | Faster algo hardcoded to 512x512 (no ratio respected) |
FastResize | A much faster resize algo that uses SIMD. For some reason it fails on some images where resized doesn't, for this reason it doesn't replace but rather it's a new option. |
Kmeans | Kmeans is an algo that divides and picks pixels all around the image, Requires more tweaking and more in depth testing but, for the most part, "it just werks". |
To edit this value:
- Config file:
backend = "full"
- Cli:
wallust run image.png --backend full
Check Constrast
Ensures a "readable contrast". Should only be enabled when you notice an unreadable contrast frequently happening with your images. The reference color for the contrast is the background color. (default: disabled)
To edit this value:
- Config file:
check_contrast = true
- Cli:
wallust run image.png --check-contrast
color_space
What colorspace to use to gather the most prominent colors.
Name | Description |
---|---|
lab | Uses Cie L a b color space. (mixed and ansi) |
lch | CIE Lch, you can understand this color space like LAB but with chrome and hue added, which Could help when sorting. (mixed) |
There are two variants:
- mixed, which mixes colors when collecting them into a histogram.
- ansi, Tries to get a full color pallete similar to the one of a tty, this works best with
ansidark
palette.
Overview
Below, is a complete overview of all colorspaces variations:
Color Space | Description |
---|---|
Lab | Uses Cie Lab color space |
LabMixed | Variant of lab that mixes the colors gathered, if not enough colors it fallbacks to usual lab (not recommended in small images) |
Lch | CIE Lch, you can understand this color space like LAB but with chrome and hue added. Could help when sorting. |
LchMixed | CIE Lch, you can understand this color space like LAB but with chrome and hue added. Could help when sorting. |
LchAnsi | Variant of Lch which preserves 8 colors: black, red, green, yellow, blue, magenta, cyan and gray. This works best with 'darkansi' palette, allowing a constant color order. |
To edit this value:
- Config file:
color_space = "lchmixed"
- Cli:
wallust run image.png --colorspace lchmixed
Fallback Generator
This field chooses a method to use when the gathered colors aren't enough:
Name | Description |
---|---|
interpolation | (default) Tries to pick two colors and built gradients over them |
complementary | Uses the complementary colors of two colors, or more (if needed), colors. |
To edit this value:
- Config file:
fallback_generator = "complementary"
- Cli:
wallust run image.png --fallback-generator complementary
Palette
Uses the colors gathered from color_space
in a way that makes sense,
resulting in a scheme palette.
Name | Description |
---|---|
ansidark | Dark ansi colors, works best with lchansi and orders it's colors to preserve a constant tty like order: color0 -> black, color1 -> redish, color2 -> greenish, and so on. |
dark | Dark colors dark background and light contrast. (16, comp, comp16) |
harddark | Same as dark with hard hue colors. (16, comp, comp16) |
light | Light bg dark fg. (16, comp, comp16) |
softdark | Variant of softlight uses the lightest colors and a dark background could be interpreted as dark inversed. (16, comp, comp16) |
softlight | Light with soft pastel colors counterpart of harddark. (16, comp, comp16) |
Palette Variations
There are some variants to the principal palettes schemes which you can use by
appending the variant to the name e.g. 'dark16
', 'lightcomp
', 'harddarkcomp16
'
and so on, each palette indicates, in parenthesis, which variants are
avaliable.
Name | Description |
---|---|
16 | Makes shades of colors, creating the ilusion of 16 different colors. |
comp | Stands for Complementary and completly changes the palette to it's complementary counterpart. |
comp16 | Complementary palette with 16 shades, basically a combination of the above. |
Overview
Below, is a complete overview of all palette schemes:
Palette | Description |
---|---|
Dark | 8 dark colors, dark background and light contrast |
Dark16 | Same as dark but uses the 16 colors trick |
DarkComp | This is a dark variant that changes all colors to it's complementary counterpart, giving the feeling of a 'new palette' but that still makes sense with the image provided. |
DarkComp16 | 16 variation of the dark complementary variant |
AnsiDark | This is not a 'dark' variant, is a new palette that is meant to work with lchansi colorspace, which will maintain 'tty' like color order and only adjusting the colors acording to the theme. A possible solution for LS_COLORS and the like. Should workout with other colorspace, but the result may not be optimal. |
HardDark | Same as dark with hard hue colors |
HardDark16 | Harddark with 16 color variation |
HardDarkComp | complementary colors variation of harddark scheme |
HardDarkComp16 | complementary colors variation of harddark scheme |
Light | Light bg, dark fg |
Light16 | Same as light but uses the 16 color trick |
LightComp | complementary colors variation of light |
LightComp16 | complementary colors variation of light with the 16 color variation |
SoftDark | Variant of softlight, uses the lightest colors and a dark background (could be interpreted as dark inversed) |
SoftDark16 | softdark with 16 color variation |
SoftDarkComp | complementary variation for softdark |
SoftDarkComp16 | complementary variation for softdark with the 16 color variation |
SoftLight | Light with soft pastel colors, counterpart of harddark |
SoftLight16 | softlight with 16 color variation |
SoftLightComp | softlight with complementary colors |
SoftLightComp16 | softlight with complementary colors with 16 colors |
To edit this value:
- Config file:
palette = darkcomp16
- Cli:
wallust run image.png --palette darkcomp16
Saturation
Color saturation, usually something higher than 50 increases the saturation and below decreases it (on a scheme with strong and vivid colors).
Possible values: 1 - 100 (default: disabled)
To edit this value:
- Config file:
saturate = 20
- Cli:
wallust run image.png --saturation 20
Threshold
Wallust automatically uses the best threshold, heuristically, if this variable isn't defined (default behaviour).
If you really want to define this variable, keep in mind the following. Thershold is the difference between similar colors , used inside the colorspace.
Each colorspace may have different results with different thresholds, meaning you should try which one works for you best.
An overall table looks like this:
Number | Description |
---|---|
1 | Not Perceptible by human eyes. |
1 - 2 | Perceptible through close observation. |
2 - 10 | Perceptible at a glance. |
11 - 49 | Colors are more similar than opposite. |
100 | Colors are exact opposite. |
To edit this value:
- Config file:
threshold = 10
- Cli:
wallust run image.png --threshold 18
Configuration File
While wallust
can work out without a config file, it results useful to
define constant options in a file than giving them each time as a cli flag.
This is why all parameters are optional.
Without a config file, wallust
will choose to default implementations, which
are explained in detail in the parameters section.
That being said, you can start editing your config file.
Format
The chosen format for the config file is Tom's Obvious Minimal Language (TOML).
You can check the full specification here.
Structure
The config file is divided into two parts:
global
spacetemplates
space
Inside the global space you can define any parameter that you want.
To enter the templates space, however, requires a [templates]
header.
Below this, you can only define templates, which is explained in the next page.
Defining a template in the config file
Templates are optional and defined inside the [templates]
header. Here it's
recommended to use single quotes ('
) instead of double quotes ("
) since the
first one, by the toml format, ignores backslashes (\
) as escape codes,
allowing you to define Widows like paths, e.g. 'C:\Users\Desktop\'
.
template
A relative path that points to a file where wallust.toml is located, usually at
~/.config/wallust/templates
. This file can also be a directory, which will be
templated non-recursively (only the first recursion, like du ... --max-depth 1
)
Check out templates
section for more.
target
Absolute path in which to place a file with generated templated values. This
field CAN expand the ~
as the $HOME
enviromental variable. If
template is a directory, this must correspond and be one.
pywal (optional)
Indicates to treat template as a pywal template, using {variable}
syntax. (default: false)
While the implementation mostly works out, it isn't a garantee that it will work all the time. If you are making a new template, make sure you do it with the new syntax
Configuration Sample
Below is a simple example exahusting all possible cases (syntax wise) in the
[templates]
header. All the format is correct:
# Let's keep good old pywal look and feel
backend = "wal"
#color_space = "lch" # idc about this one..
#threshold = "20" # neither about this, since I read wallust does it automagically..
# classic look
palette = "dark16"
# let's keep the contrast very very very clear.
check_contrast = true
[templates]
# dunst templates
dunst.template = "dunstrc.monitor"
dunst.target = "~/.config/dunst/dunstrc"
# one liner for zathura
zathura = { template = 'zath', target = '~/.config/zathura/zathurarc' }
# even a shorter way
glava = { src = 'glava.glsl', dst = '~/.config/glava/rc.glsl' }
# or splited in the dotted syntax
res.src = "xres"
res.dst = "~/.config/Xresources"
# old times, good times, here I put old pywal templates. Seems unstable tho.
# NOTE THAT BOTH scr AND dst ARE DIRECTORIES!
pywal = { src = "templates/", dst = '~/.cache/wal/', pywal = true }
Templates
A template is simply a file that has placeholders in order to replace them with values. In wallust case, these values can range from either the colors generated, the image/theme served or the backend used. These values are represented by variables, which you can look up inside placeholders.
By using templates you can apply the colors to a program that uses a config file.
I've made some templates for some known programs at https://codeberg.org/explosion-mental/wallust-templates. If you have a template you want to share, that is the place.
Where?
The default templates directory is at CONFIG/wallust/templates
, where CONFIG
changes depending the platform wallust is ran at (e.g. $XDG_CONFIG_HOME
in linux). Check out features
section.
You can also change this in cli with --templates-dir
.
Template Syntax
Here is an overview of the general syntax of a template.
You reference variables in the following syntax:
{{color0}}
For applying a filter you use the pipe character (|
) like this:
{{background | strip}}
And if the filter requires an argument:
{{background | lighten(0.3)}}
Remember that filters require a valid type to apply to in these examples we are using colors, which can even be defined literally:
{{ "#4ff4ff" | lighten(0.3)}}
For both, being applied to or as an argument of a filter:
{{ color2 | blend("4ff4ff")}}
If you need to write a literal {{
, that doesn't references any variable, you
can write literals inside the delimiters:
{{ "{{" }} {{ "}}" }}
You can also use control flow expressions with {% %}
delimiters:
{% if backend == "wal" %}
I am using the '{{backend}}' backend, getting a pywal like scheme.
{% elif backend == "fastresize" %}
This backend is called "{{palette}}" and, uses SIMD optimizations and is so fast!
{% else %}
I don't care about any other backends. Be happy!
{% endif %}
Or inline them:
{{ "I'm using the kmeans algo!" if backend == "kmeans" else "Some backend is in use" }}
Since mostly everything can be represented as a string (we've seen how colors are represented), indexing results very useful! The syntax for indexing is basically the Python one.
{# I'll hardcode a color based on the palette being used. #}
{% if palette[:4] == "dark" %}
somevariable = "#eeffbb"
{% else %}
somevariable = "#aabbee"
{% endif %}
And yes, you can comment inside your template, the comments won't be rendered in the final target file:
{# This won't be visible! #}
There are more control flow instructions, like the for loop:
{# This will generate color0 = .. to color18,
since `colors` contains background, foreground and cursor variables #}
{% for c in colors %}
color{{- loop.index }} = {{c-}}
{% endfor %}
You can add a minus sign (-) at the start or the end of the delimiters to supress vertical spacing (White space control with the minus sign -
)
The syntax comes from the library being used, which is minijinja, a subset of the template engine 'Jinja2'.
You can read more at: Jinja2 official syntax and contrast features with the supported syntax at Compatibility of minijinja
Template Variables
The "color" type
These types are formated like as HEX rgb (e.g. '#0A0B0C') by default. However a
color literal can be represented in multiple ways, like HEXA rgba (e.g.
'#0A0B0CFF
', where 'FF
' is the transparency value) or HEX rgb without the
leading '#
' ('0a0b0c
').
Avaliable values:
- color0
- color1
- color2
- color3
- color4
- color5
- color6
- color7
- color8
- color9
- color10
- color11
- color12
- color13
- color14
- color15
- background
- foreground
- cursor
colors
Additionally, this variable (colors
) returns a vector of all the presented colors in the following order:
Starts with color0 to color15, background, foreground and at the end, (index 18 if starting from 0), cursor.
MISCELLANEOUS
Other avaliable variables:
wallpaper
The full path to the current wallpaper, colorscheme file or the name of the theme in use.
backend
Current backend being used.
colorspace
Current colorspace being used.
palette
Current palette being used.
alpha
Default to 100, can be modified in the config file or with --alpha
/-a
.
alpha_dec
Instead of 0 to 100, displays it from 0.00 to 1.00.
Template Filters
The Jinja2 format calls them 'filters', making a distincion from 'functions'.
Currently I haven't implemented any function because I haven't found a usecase (yet?).
Filters that take an UNSIGNED INT
alpha_hexa
Displays alpha value as
hexadecimal color code
(e.g "{{ 100 | alpha_hexa }}
" outputs 'FF
').
This can only be used with numbers from 0 to 100, so you are free to use the
variable alpha with this filter.
Filters that take the color type
Functions that only work with colors. These can be applied to a color, which
can be the COLOR variables listed in "Variables" section, or a literal color
like "#0A0B0C
". These functions return a color in the mentioned format (hex
rgb, like "#000000
"), unless written otherwise (like rgb, rgba, the other
filters that explicitly say it's output format). This allows to apply multiple
filters at a time.
Note: If an 'alpha' value is mentioned, it's defined in the config file, as a cli flag and by default it's value is '100'.
hexa
Outputs the color in hexa
format: e.g "#0A0B0CFF
", where 'FF
' is the alpha value. .
Note: This, internally uses alpha_hexa
filter from above.
Example:
{{ color5 | hexa }}
rgb
Output the color in rgb
, separated by comas. (e.g. "10,11,12")
xrgb
Output the color in xrgb
, separated by slashes. (e.g "0A/0B/0C")
strip
Output the color in hex
, just like by default, but removes the leading #
. (e.g. "0A0B0C")
red
Outputs only the red value. (e.g. "10")
green
Outputs only the green value. (e.g. "11")
blue
Outputs only the blue value. (e.g. "12")
complementary
Returns the respective complementary color.
blend
Takes another color as input, to blend it for the filtered color.
Example:
{{ color2 | blend(color0) }}
lighten
Takes a float (decimal value) as input, from 0.1
to 1.0
, that corresponds
to the amount to lighten the color by.
Example:
{{ color0 | lighten(0.2) }}
darken
Takes a float (decimal value) as input, from 0.1
to 1.0
, that corresponds to the amount to darken the color by.
saturate
Takes a float (decimal value) as input, from 0.1
to 1.0
, that corresponds to the amount to saturate the color by.
Example
# zathurarc config sample
...
# colors
set default-bg "{{background}}"
set default-fg "{{foreground}}"
# make it a bit lighter than background
set statusbar-bg "{{background | lighten(0.3)}}"
# make it darken by blending to a darken color
set statusbar-fg "{{foreground | blend("#eeeeee")}}"
# use it's complementary
set inputbar-bg "{{background | complementary}}"
Then you can add this file to ~/.config/wallust/templates
and use the config file to template it. For example,
zathura.template = 'zathurarc'
, and then define a
target field, see config.
Pywal Template Compatibility
You can enable pywal like syntax in the config file with pywal = true
.
wallust (5)
The syntax is simple, but more variables are added given that it's engine and spec doesn't support runtime evaluation functions.
While the implementation is simple enough to be added in wallust, it's use is discoraged.
Syntax
The syntax logic is simply "Find and Replace" like:
somevariable = {color2}
anothervariable = {color8.rgb}
Don't forget to visit the full pywal spec
Variables
- color0
- color1
- color2
- color3
- color4
- color5
- color6
- color7
- color8
- color9
- color10
- color11
- color12
- color13
- color14
- color15
- background
- foreground
- cursor
and it's variants, just append it to the variable name (e.g. color0.rgb
, background.blue
...):
- .rgb
- .rgba
- .xrgba
- .strip
- .red
- .green
- .blue
Miscellaneous variables below are also avaliable, these don't support the variants from above:
- wallpaper
- alpha
- alpha_dec
Contribute!
Show some of your taste by adding a backend, colorspace, scheme palettes, and/or a custom theme.
Having design ideas or suggestios is also very welcome.
TODOs
Some food for thought.
-
wallust init
, which will scan your system for common aplication in which there is an avaliable theme template at wallust-templates. If so, it will automatically fetch those templates, add it in your toml config and configure accorndingly. Make it interactive. -
Allow to have more than 6 (MIN_COLS) passed to
palettes
. This requires some comunication to be exchanged betweenColorSpace <-> Palette
modules. -
Learn more from "Material You" implementations, what I've seen is that it looses some colors and hues to mantain contrast.
-
Pulish code on colorspaces
-
Implement a 1 to 1 replica template engine for pywal (It seems that the pywal syntax for templating will remain standard)
For more, grep the src for TODO rg TODO
Packaging
Binary-based distros can grab the latest pre-compiled binary from the releases page.
Source-based distros, if they wish to build wallust
from source, must ensure
that the following dependencies are available:
- Build Dependencies:
- Rust (
cargo
,rustc
) - make (or install man pages and completions manually)
- Rust (
- Runtime Dependencies
imagemagick
is required only for thewal
backend, such limiting should be mentined and considered an optional dependency, since all other backends work without it.
Makefile
Using make
is optional if you know your way into cargo and can accept
the job to manually install man pages, completions and the binary.
I've only added a Makefile
to simplify installing these assets, as well as
the binary. By default make
uses native compilation, you can define your
wished target like this:
Building
$ TARGET=x86_64-pc-windows-gnu make install CARGOFLAGS="--release --target=$TARGET"
Installing
# TARGET=x86_64-pc-windows-gnu make CARGOFLAGS="--release --target=$TARGET" RELEASE="target/$TARGET/release"
Don't forget that make
by itself runs cargo
in order to built the binary.
It's common on projects that use make to split building in two steps, given
that make install
requires permissions to write on $DESTDIR$PREFIX
.