Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Niji

Niji is an extensible theming framework that brings uniform, responsive and comfortable theming to the tinkerer’s desktop. It currently comes with builtin support for GTK apps, sway, hyprland, kitty, and others, but it also allows you to easily add custom modules for anything you desire.

Refer to Getting Started for a quick guide on how to set niji up, or take a look at Configuration and Built-in Modules for a more in-depth reference of niji’s capabilities.

Getting Started

Installation

AUR

Arch Linux users can install niji from the AUR using the niji-git package.

Manually

To install niji manually from source, do the following steps:

  1. Make sure you have the rust toolchain and just installed
  2. Clone the git repository and enter the folder
  3. Build the project using just build
  4. Install niji using sudo just install

Initial Configuration

Create the configuration file at ~/.config/niji/config.toml. The first step is to choose which modules to use. Take a look at Built-in Modules for a list of available modules. Simply set your desired modules using this syntax:

modules = ["hyprland", "waybar"]

Afterwards, you should set font_family, cursor_theme and cursor_size as basic preferences. Make sure you have the cursor theme installed that you select.

modules = ["hyprland", "waybar"]

[global]
font_family = "Fira Sans"
cursor_theme = "Adwaita"
cursor_size = 22

Lastly, be sure to refer to the documentation of each of your selected modules and check for available configuration options and additional necessary steps for activation.

You can now list available themes using niji theme list, and preview them using niji theme preview <name>. You can also choose an accent color out of pink, red, orange, yellow, green, teal, blue, purple, black and white.

If you’ve picked a theme and accent color, apply it using:

niji theme set <theme> --accent <accent>

Next Steps

After the initial setup, you may want to consider taking a look at Configuration for some advanced configuration options.

If you want to use a custom theme, refer to Custom Themes.

If you want to apply your theme to an application that isn’t supported out of the box, you can take a look at Custom Modules.

Configuration

Niji is configured via its config file, which lies at ~/.config/niji/config.toml (Assuming you don’t have a custom $XDG_CONFIG_HOME set). The config file uses TOML syntax.

Base Configuration

The base configuration configures the behavior of the niji framework itself. These options go at the top level of config.toml. Currently, the following options are available:

# A list of module names to activate.
# This value is required.
modules = []

# A list of module names that shouldn't be automatically reloaded.
# This is useful if the reloading behavior of that module interferes with your
# specific configuration.
disable_reloads = []

Module Configuration

Configuration options for modules appear after a header containing their name. The one exception is the special [global] header, which applies to all modules.

All module configuration options are optional, but if you want consistency across different theming targets, it is a good idea to set the available global options that make sense for your setup, since default behaviors may differ from module to module.

Global Options

The available global module configuration options are as follows, shown here with example values:

[global]

# The font family to use for UI
font_family = "Fira Sans"

# A scaling factor for text.
# Use this if you want larger text for better visibility, or smaller text for
# a more compact UI.
font_scale = 1.0

# The cursor theme to use
cursor_theme = "Adwaita"

# The cursor size to use
cursor_size = 22

You can also override any of these options individually for each module, simply by adding to the corresponding section. For example, you could configure the waybar module to use a different font like this:

[waybar]
font_family = "Fira Code"

Setting Wallpapers per Theme

If you have a module that supports setting wallpapers, such as hyprpaper, you can set a global wallpaper map, that specifies which wallpaper to use for each theme. You can do this by adding a [global.wallpaper] heading to your config, with keys corresponding to the theme names, and values corresponding to the path to the wallpaper. You can also add a default key as a fallback.

An example configuration might look like this:

[global.wallpaper]
default = "./wallpapers/wp1.png"
tokyonight = "./wallpapers/wp2.png"
dracula = "./wallpapers/wp3.png"

If you just want to use a single wallpaper for every theme, you can also just set the wallpaper option like this:

[global]
wallpaper = "./wallpaper/my-wallpaper.png"

Module-Specific Options

Module-specific options come after a header with the name of the corresponding module. An example configuration for the waybar module might look like this:

[waybar]
icon_font = "Material Design Icons"
show_shadow = false
module_margin = 8

What specific options are available differs from module to module. If you are using a builtin module, you can find their respective documentation in Built-In Modules.

Command Line Interface

To get a full list of CLI options, use niji help or niji help <command>.

Setting the theme and accent color

Get a list of available themes using:

niji theme list

To preview a theme from the list, use:

niji theme preview <theme> --accent <accent>

<accent> can be one of pink, red, orange, yellow, green, teal, blue, purple, black or white.

To set a theme with a certain accent color use:

niji theme set <theme> --accent <accent>

To set the theme individually and keep the current accent color, simply omit the accent argument:

niji theme set <theme>

To change the accent color and keep the current theme, use:

niji accent set <accent>

Applying re-applying modules

If you want to manually re-apply the current theme and accent color, use:

niji apply

To (re-)apply a specific module, use:

niji apply --module <name>

Built-in Themes

Niji includes a number of built-in themes. You can preview them using the niji theme show <name> command, and select them using niji theme set <name>. For more information, refer to Command Line Interface.

The built-in themes currently included with niji are:

  • catpuccin-frappe
  • catpuccin-latte
  • dracula
  • gruvbox
  • gruvbox-light
  • tokyonight

To list these themes, along with any custom or separately installed themes, use the niji theme list command.

If there is something missing from this list that you’d like to have, take a look at Custom Themes.

Built-in Modules

Niji includes a number of modules already built-in. You can simply activate them by adding their names to the "modules" list in your config.toml. For more details, see Configuration, and the documentation of the respective module.

The built-in modules currently included with niji are:

  • gtk: Theming GTK3 and GTK4 applications
  • qt: Theming QT5 and QT6 applications
  • hyprland: Theming hyprland window decorations
  • hyprpaper: Wallpaper setting support for hyprpaper
  • kitty: Theming kitty window and terminal colors
  • mako: Theming mako notifications
  • sway: Theming sway window decorations and setting swaybg wallpapers
  • swaylock: Theming your swaylock lock screen
  • waybar: A fully managed waybar theme
  • wob: Theming wob indicators

If there is something missing from this list that you’d like to have, consider writing a Custom Module.

Module gtk

The gtk module allows you to theme GTK3 and GTK4 applications. Note that other targets for GTK themes, such as GTK2, qt6gtk2, gnome-shell, etc. are currently not supported.

The niji theme is a modified version of the amazing Colloid theme by vinceliuice.

Activating

To activate the module, add it to your config.toml:

modules = ["gtk"]

This will export a GTK theme called “niji” to your system. If you have reloads enabled for this module (which they are by default), niji will also automatically set the system GTK theme when applying. If you don’t want this behavior, you can disable it by adding "gtk" to your disable_reloads list (see Configuration).

libadwaita

Apps that use libadwaita, such as nautilus, are quite stubborn when it comes to convincing them to use a gtk theme other than Adwaita. The easiest way to fix this is to globally set the environment variable GTK_THEME to niji, which works.

If you are using Arch Linux, you can also use libadwaita-without-adwaita-git for an arguably cleaner solution; this patched version of libadwaita properly respects your system GTK theme, and makes apps like nautilus work properly with niji, nwg-look, and other tools, out of the box.

Configuration

The following global configuration options are relevant to this module:

  • cursor_theme
  • cursor_size
  • font_family
  • font_scale

See Configuration for a detailed explanation. Note that these options do not work if reloads are disabled for this module.

Additionally, these module-specific configuration options can be added to config.toml (shown here with their default values):

[gtk]

# Set to true to use a more compact layout in GTK apps
compact = false

# Set to "normal" for less flashy window buttons
window_button = "mac"

Module qt

The qt module allows you to theme QT5 and QT6 applications, using qt5ct and qt6ct respectively, using niji.

This module does not currently support font configuration. Please use qt5ct and qt6ct to set those manually.

Important

This module will only work properly if you select ‘niji’ as the color scheme in both qt5ct and qt6ct!

Activating

To activate the module, add it to your config.toml:

modules = ["qt"]

This will export a color scheme called “niji” to your system that can be used by qt5ct and qt6ct. If you have reloads enabled for this module (which they are by default), niji will also force-reload the styles of all running qt applications upon application.

Module hyprland

The hyprland module allows you to theme the window decoration of the Hyprland wayland compositor.

The configuration produced by this module is intentionally minimal, and does not interfere with your existing hyprland config.

See also the hyprpaper module.

Activating

To activate the module, add it to your config.toml:

modules = ["hyprland"]

Niji will now output a hyprland configuration file to ~/.local/share/niji/hyprland/theme.conf. To enable it, add the following line to the bottom of your hyprland.conf:

source = ~/.local/share/niji/hyprland/theme.conf

You can, of course, override as much of the generated configuration as you like, simply by adding configuration after the source statement.

Configuration

The following global configuration options are relevant to this module:

  • cursor_theme
  • cursor_size

See Configuration for a detailed explanation.

Additionally, these module-specific configuration options can be added to config.toml (shown here with their default values):

[hyprland]

# Set to true to use a muted border color for focused windows instead of
# the accent color
muted_border = false

Module hyprpaper

The hyprpaper module allows you to automatically reconfigure hyprpaper to use a specific wallpaper for each theme.

See also the hyprland module.

Activating

To activate the module, add it to your config.toml:

modules = ["hyprpaper"]

This will cause niji to take control of your .config/hypr/hyprpaper.conf file.

Configuration

In order for this module to do anything, you have to have a wallpaper map configured. See Setting Wallpapers per Theme for information on how to do that.

Beyond that, these module-specific configuration options can be added to config.toml (shown here with their default values):

[hyprpaper]

# Set to true to show the hyprland splash text on the wallpaper
splash = false

# Set the fit mode. See the hyprland docs for details:
# <https://wiki.hypr.land/Hypr-Ecosystem/hyprpaper/>
fit_mode = "cover"

# The command to be used to start hyprpaper when restarting it
hyprpaper_command = "hyprpaper > /dev/null"

Module kitty

The kitty module allows you to set the window and terminal colors for the kitty terminal emulator.

Activating

Th activate the module, add it to your config.toml:

modules = ["kitty"]

This will create a kitty theme called “niji”. If you have reloads enabled for this module (which they are by default), niji will also automatically apply this theme. If you do not want this behaviour, you can disable it by adding "kitty" to your disable_reloads list (see Configuration).

Configuration

These module-specific configuration options can be added to config.toml (shown here with their default values):

[kitty]

# The opacity of the terminal background
background_opacity = 1.0

# The foreground color. Can be any key from the [terminal] section of the theme,
# or a custom color, such as "#ff0000".
foreground = "bright_white"

Module mako

The mako module allows you to theme notifications produced by the mako notification daemon.

Activating

To activate the module, add it to your config.toml:

modules = ["mako"]

This will cause niji to take control of your .config/mako/config file.

Configuration

The following global configuration options are relevant to this module:

  • font_family
  • font_scale

See Configuration for a detailed explanation.

Additionally, these module-specific configuration options can be added to config.toml (shown here with their default values):

[mako]

# The border width around notifications
border_width = 2

# The border radius of notifications
border_radius = 10

# The background transparency of the popup
popup_alpha = 1.0

# Set to a path string to set more configuration options
custom_config_file = false

Since niji needs to take control of .config/mako/config, if you want to set any of mako’s numerous additional configuration options that have nothing to do with theming, you’ll have to create a separate configuration file in your .config/niji directory, and link to it in config.toml. For example, if you wanted to set the default timeout of notifications, you might do something like this:

~/.config/niji/config.toml

# ...

[mako]
custom_config_file = "./custom/mako_config"

~/.config/niji/custom/mako_config

default-timeout=10000

Module sway

The sway module allows you to theme sway window decorations, as well as setting your swaybg wallpaper per theme.

Activating

To activate the module, add it to your config.toml:

modules = ["sway"]

Niji will now output a sway configuration file to ~/.local/share/niji/sway/theme. To enable it, add the following line to the bottom of your sway config:

include ~/.local/share/niji/sway/theme

If you want to override any of the settings exported by niji, you can simply add more configuration after the include statement.

Configuration

The following global configuration options are relevant to this module:

  • font_family
  • font_scale
  • cursor_theme
  • cursor_size
  • wallpaper

See Configuration for a detailed explanation. In particular, see Setting Wallpapers per Theme for information on the wallpaper setting.

Additionally, these module-specific configuration options can be added to config.toml (shown here with their default values):

[sway]

# Set to true to use a muted border color for focused windows instead of
# the accent color
muted_border = false

# Set to true to display sway's indicator bar to show where the next window
# will open
show_indicator = false

# Set to true to prevent niji from managing the wallpaper via swaybg
disable_wallpaper = false

# Set to true to prevent niji from setting swaybar styles
disable_swaybar = false

Module swaylock

The swaylock module allows you to theme your swaylock lock screen.

Activating

To activate the module, add it to your config.toml:

modules = ["swaylock"]

This will cause niji to take control of your .config/swaylock.config file.

Configuration

The following global configuration options are relevant for this module:

  • font_family
  • font_scale

See Configuration for a detailed explanation.

Additionally, these module-specific configuration options can be added to config.toml (shown here with their default values):

[swaylock]

# Set to a path string to set additional configuration options
custom_config_file = false

This module is only concerned with setting colors. Any additional configuration of swaylock, particularly if you are using something like swaylock-effects, needs to be done in a separate custom configuration file. An example configuration might look like this:

~/.config/niji/config.toml

# ...

[swaylock]
custom_config_file = "./custom/swaylock_config"

~/.config/niji/custom/swaylock_config

clock
indicator
grace=3
fade-in=1

Module waybar

The waybar module provides a fully managed waybar theme in line with your system’s niji theme.

Activating

To activate the module, add it to your config.toml:

modules = ["waybar"]

This will cause niji to take control of your .config/waybar/style.css file.

Configuration

The following global configuration options are relevant for this module:

  • font_family
  • font_scale

See Configuration for a detailed explanation.

Additionally, these module-specific configuration options can be added to config.toml (shown here with their default values):

[waybar]

# Set to the ids of custom modules that you use (e.g. "custom-gpu"),
# in order for them to be styled properly.
custom_modules = []

# Set to a string to specify a font to use for icons,
# such as FontAwesome or Material Desing icons
icon_font = false

# Set to false to disable shadows behind waybar elements
show_shadow = true

# The opacity of waybar when in a hidden state
hidden_opacity = 0.0

# The padding in pixels of waybar elements in the x direction.
padding_x = 12

# The padding in pixels of waybar elements in the y direction.
padding_y = 4

# The margin between workspace buttons in pixels
workspace_button_margin = 6

# Set to the path to a css file to include arbitrary custom styles
custom_style_file = false

Note, in particular, the custom_modules option. If you use custom modules, you have to add them to the list, otherwise they won’t be styled properly.

More Customization

Since waybar is, by its nature, highly customizable, this module is not going to fit many people’s use cases. You can try to fiddle around with the custom_style_file configuration option, but if you already have a highly customized waybar theme, I recommend you check out Creating Custom Modules.

Module wob

The mako module allows you to theme wob bars.

Activating

To activate the module, add it to your config.toml:

modules = ["wob"]

This will cause niji to take control of your .config/wob/wob.ini file.

Note that if you want live reloading to work, you will likely need to configure a wob_command. See the following for details.

Configuration

These module-specific configuration options can be added to config.toml (shown here with their default values):

[mako]
# The command used to start wob when reloading
wob_command = "tail -f $XDG_RUNTIME_DIR/wob.sock | wob"

# Set to a path string to specify custom values for wob.ini
custom_config_file = false

Due to the nature of how wob functions, it is likely necessary to customize the wob_command option to get live reloading to function correctly. Simply set it to the same command that you use to start wob initially.

Since niji needs to take control of .config/wob/wob.ini, if you want to set any of wobs’s additional configuration options, or override a value set by niji, you’ll have to create a separate configuration file in your .config/niji directory, and link to it in config.toml. For example, if you wanted to show the bar at the top of the screen, you might do something like this:

~/.config/niji/config.toml

# ...

[wob]
custom_config_file = "./custom/wob.ini"

~/.config/niji/custom/wob.ini

anchor = top

Custom Themes

If you build a custom theme, consider contributing it! Just make sure you have the proper license for the color scheme you’re using, as color schemes may be subject to copyright.

Custom niji themes are defined using TOML files placed into the ~/.config/niji/themes directory, with the filename (without the extension) matching the theme name.

Basics

The minimal configuration required for a theme is to set kind to either "light" or "dark", based on whether it should use dark text on a light background, or light text on a dark background respectively, and to specify all the required palette colors under [palette], as per the following example. All colors are specified using #RRGGBB or #RRGGBBAA syntax.

kind = "dark"

[palette]
blue = "#7aa2f7"
yellow = "#e0af68"
orange = "#ff9e64"
red = "#f7768e"
pink = "#f293a5"
green = "#9ece6a"
teal = "#73daca"
purple = "#bb9af7"
white = "#c0caf5"
black = "#1a1b26"

niji will then derive all required colors for all theming modules from the specified color palette.

Overrides

In cases where you want more direct control over colors used in specific circumstances, you can override niji’s automatic color derivation. The [ui] section can be used to override colors used for graphical user interfaces, and the [terminal] section to override ANSI terminal colors.

Color overrides can be set either by setting an explicit color like under [palette], by referencing a palette color by name, or by using inline color derivation syntax to lighten or darken a palette color by some amount, choose a specific shade with the same hue and chroma, and/or to modify the color’s alpha value.

[ui]
border = "#333333" # Set an explicit color
surface = "black" # Reference a palette color

# Inline color derivations
warning = { color = "orange", darken = 0.1 } # Darken palette orange by 10%
error = { color = "red", lighten = 0.2 } # Lightn palette red by 20%
success = { color = "teal", shade = 0.9 } # Pick a shade wtih 90% lightness based on palette teal
shadow = { color = "black", alpha = 0.2 } # Set the alpha channel of palette black to 0.2

[ui]

The [ui] section is used for color overrides for graphical interfaces. It contains the following options:

OptionDescription
backgroundThe main background color
surfaceThe background color of surfaces that appear on top of background (such as panels or cards)
borderThe color of borders around certain elements. May be set to transparent (#00000000) to remove borders.
shadowThe color of drop shadow around certain elements. May be set to transparent (#00000000) to remove drop shadows.
text_lightThe light text color to use on dark backgrounds.
text_darkThe dark text color to use on light backgrounds.
successThe color indicating a successful action. Usually a shade of green.
warningThe color used for warning messages. Usually a shade of yellow or orange.
errorThe color used for error messages and states. Usually a shade of red.

[terminal]

The [terminal] section contains color overrides corresponding to the standard 16 ANSI colors:

  • dark_black
  • dark_red
  • dark_green
  • dark_yellow
  • dark_blue
  • dark_magenta
  • dark_cyan
  • dark_white
  • bright_black
  • bright_red
  • bright_green
  • bright_yellow
  • bright_blue
  • bright_magenta
  • bright_cyan
  • bright_white

As well as the following additional options:

OptionDescription
defaultThe default color to use for non-colored terminal text. Usually a shade of white or black.
shade_differenceThe difference in lightness to use when deriving dark and bright terminal colors from each other

Custom Modules

If you build a custom module, consider contributing it! PRs are always welcome
)

Custom modules are located in the directory ~/.config/niji/modules. Each module is a folder in that directory; the name of the folder is the module name.

The heart of a niji module is a lua module in the module folder called module.lua. It has this general structure:

local M = {}

function M.apply(config, theme, accent)
    -- Apply the theme here
end

function M.reload(config)
    -- Reload the application here.
end

return M

The module defines two handlers, apply and reload.

The apply handler receives the module config, the theme and the accent color as parameters. It is responsible for taking the theme, transforming its contents and writing them to where they need to go for the theming target to use them.

The reload handler is optional. It is responsible for reloading the theming target to apply the new config. The reason why these two are separate is so that niji can more easily tell which modules support live reloading, and so that users can selectively disable live reloading for certain modules.

The exact semantics of the two handlers are different depending on the nature of the theming target, but in general, apply should apply the theme and config in the least invasive way possible, while reload does whatever is necessary to live-reload the theming target.

Module Config

The module config, which is passed as the first parameter to both the apply and the reload handlers, is a table with string keys and arbitrary values. It comes from combining the module-specific configuration for your module with the global module configuration, both of which are defined in config.toml. See Configuration for more information.

Simple modules for personal use probably won’t use this feature much, but it is recommended that modules which are used by multiple users and may be merged to be builtin modules use the config feature to provide options to users, and conform to certain global configuration options like font_scale.

Theme

The theme has fields that corresponds directly to the theme format documented in Custom Themes. All color values in the theme are passed as a niji.Color instance.

It also provides some additional utilities related to text colors:

-- Get the default text color
niji.ui.text_default

-- Get the text color for a specific background color:
niji.ui:text_on(background_color)

Lua API

Niji provides its own Lua API for building modules. It is fully documented in the section Lua API Reference.

Templates

A very common thing that modules need to do is inserting some values from the theme into a pre-made config file template. niji provides a builtin system to do this, which is documented in the section Templating Reference, and can be used via the niji.Template class from the Lua API.

Lua API Reference

niji’s Lua API resides in the global niji namespace. There is no need to import it. The niji namespace contains several sub-namespaces and classes for different purposes, which are listed in this document.

In addition, you can always use the Lua standard library which is fully supported. If one of the functions in the niji API fits what you want to do however, you should always prefer using the niji API, as it provides better integration and safety features.

Modules are always executed with their working directory inside of their module folder, so you can easily reference bundled assets like template files using relative paths.

Contents:

Class niji.Color

The class niji.Color represents an RGBA color. It can be used to perform certain manipulations on colors. All color manipulations use the Oklab perceptual color space, so while some results may appear unexpected through an RGB lens, they should look good.

All color fields in the theme parameter of the module application handler are also instances of niji.Color.

All functions that accept colors also accept strings of the format "#RRGGBB" and "#RRGGBBAA".

Property niji.Color.r

The red channel of the color as an integer between 0 and 255

Property niji.Color.g

The green channel of the color as an integer between 0 and 255

Property niji.Color.b

The blue channel of the color as an integer between 0 and 255

Property niji.Color.a

The alpha channel of the color as an integer between 0 and 255

Static niji.Color:new(color_string)

Constructs a new niji.Color object.

  • color_string: A string representing the desired color (string)
  • returns: The resulting color (niji.Color)
local my_color = niji.Color:new("#ab38a3ff")

-- Prints "#ab3aa3ff"
niji.console.debug(my_color)

Static niji.Color:blend(color_1, color_2, t)

Interpolates between two colors.

  • color_1: The first of the two colors to interpolate between (string or niji.Color)
  • color_2: The second of the two colors to interpolate between (string or niji.Color)
  • t: A number between 0 and 1 that controls the interpolation (float)
  • returns: The resulting color (niji.Color)
local my_color = niji.Color:blend("#ff0000", "#00ff00", 0.3)

-- Prints "#ff6300ff"
niji.console.debug(my_color)

Static niji.Color:mix(color_1, color_2)

Mixes two colors together evenly. Equivalent to calling niji.Color:blend with a t of 0.5.

  • color_1: The first of the two colors to mix together (string or niji.Color)
  • color_2: The second of the two colors to mix together (string or niji.Color)
local my_color = niji.Color:mix("#ff0000", "#00ff00")

-- Prints "#f99500ff"
niji.console.debug(my_color)

niji.Color:lighten(amount)

Lightens the color by the given amount. “Amount” here refers to relative perceived lightness, which means that the change in lightness for a given amount parameter should look the same for any base color, unless the resulting color would fall outside the RGB color gamut.

  • amount: The desired relative perceived lightness, ranging between -1 and 1 (float)
local base_color = niji.Color:new("#123faa")
local lightened_color = base_color:lighten(0.2)

-- Prints "#4a7eeeff"
niji.console.debug(lightened_color)

niji.Color:darken(amount)

Darkens the color by the given amount. Equivalent to calling niji.Color:lighten with -amount.

  • amount: The desired relative perceived lightness, ranging between -1 and 1 (float)
local base_color = niji.Color:new("#c670f9")
local lightened_color = base_color:darken(0.2)

-- Prints "#872eb5ff"
niji.console.debug(lightened_color)

niji.Color:shade(lightness)

Selects a shade of the color that has the provided absolute perceived lightness. As with other operations, if that color falls outside the RGB gamut, it gets gamut-clipped.

  • lightness: The desired perceived lightness, ranging between 0 and 1 (float)
local base_color = niji.Color:new("#cb9174")
local shade = base_color:shade(0.4)

-- Prints "#6c3a1fff"
niji.console.debug(shade)

niji.Color:with_alpha(alpha)

Returns the same color with the provided alpha value.

  • alpha: The desired alpha value, ranging between 0 and 1 (float)
local base_color = niji.Color:new("#abcdef")
local transparent_color = base_color:with_alpha(0.5)

-- Prints "#abcdef80"
niji.console.debug(transparent_color)

Class niji.Template

The class niji.Template is the lua API for niji’s builtin templating system. It can be used to load, parse and render templates.

Static niji.Template:parse(template)

Parses the provided string template as a template.

  • template: The template string (string)
  • returns: The parsed template object (niji.Template)
local my_template = niji.Template:parse("Hello {{name}}!")

Static niji.Template:load(path)

A utility method that loads a template from a file.

  • path: The path to the template file to load (string)
  • returns: The parsed template object (niji.Template)
local my_template = niji.Template:load("my_template.mustache")

niji.Template:render(value)

Render the template to a string using a given input value. This is most commonly a table of keys and values used in the template.

  • value: The value to use as an input in the template (any type)
  • returns: The rendered string (string)
local my_template = niji.Template:parse("Hello {{name}}!")
local rendered = my_template:render({ name = "World" })

-- prints "Hello World!"
niji.console.debug(rendered)

niji.Template:set_format(type_name, format_string)

Set the custom format for the specified type. See the template system reference for more information.

  • type_name: The name of the type for which to set the format (string)
  • format_string: The format string to use for the given type

Namespace niji.console

The niji.console namespace provides niji-flavored functions for interacting with the console.

niji.console.debug(message)

Sends a debug message to the console. Note that these messages are only visible if --verbose is passed as an argument to niji.

  • message: The message to send (any type)

niji.console.info(message)

Sends an info message to the console.

  • message: The message to send (any type)

niji.console.warn(message)

Sends a warning message to the console.

  • message: The message to send (any type)

niji.console.error(message)

Sends an error message to the console.

  • message: The message to send (any type)

niji.console.prompt(message, default)

Sends a confirmation prompt to the user. If default is not nil, pressing enter without entering a response will return that value. If default is nil, pressing enter without entering a response will trigger a reprompt.

  • prompt: The message to show in the prompt (any type)
  • default: The default value for the prompt (bool or nil)
  • returns: The response from the user (bool)
if niji.console.prompt("Do the thing?", true) then
    doTheThing()
end

Namespace niji.fs

The namespace niji.fs contains functions for interacting with the file system. While it is much more restrictive than the filesystem API built into lua, it is strongly recommended to use niji.fs functions over raw lua functions whenever possible, because they have a lot of extra safety features, such as automatically checking for conflicts with preexisting files.

niji.fs.write(path, content)

This function should be used when you have to write to a file that might already exist on the system, and which you might not want to silently overwrite if it does; the major example for this is configuration files which don’t support including files from other locations.

If you just want to output a file that can then be included/imported by another program, consider using niji.fs.output. This is often a better approach, because it is a lot less invasive.

Calling niji.fs.write will cause niji to check if the file already exists, and contains data that wasn’t written to it by niji. If that is the case, niji will inform the user via a prompt, and create a backup of the previous version if necessary. Ultimately, it writes content to file at the given path.

  • path: The path of the file to write to (string). You can use “~” to refer to the current user’s home directory.
  • content: The string to write to the file (string)
  • returns: The absolute, canonical path of the file written to (string)

niji.fs.write_config(path, content)

A version of niji.fs.write that takes paths relative to ~/.config.

  • path: The relative path to the config file to write to (string)
  • content: The content to write to the file (string)
  • returns: The absolute, canonical path of the file written to (string)

niji.fs.write_state(path, content)

A version of niji.fs.write that takes paths relative to ~/.local/state.

  • path: The relative path of the state file to write to (string)
  • content: The content to write to the file (string)
  • returns: The absolute, canonical path of the file written to (string)

niji.fs.write_data(path, content)

A version of niji.fs.write that takes path relative to ~/.local/share.

  • path: The relative path of the data file to write to (string)
  • content: The content to write to the file (string)
  • returns: The absolute, canonical path of the file written to (string)

niji.fs.output_artifact(config, opts)

Outputs a file to the module’s output directory, and validates that it is included in a specified config file. Prints a warning if this is not the case.

  • config: the module config passed to the apply function
  • opts: a table of options:
    • out: the file path to output to, relative to your module’s output folder, by default located at ~/.local/share/niji/<module name>
    • content: the string to write to the output file
    • sourced_by_config: the config file (or list of config files) that the out file is expected to be sourced or included by. The path is relative to ~/.config (or $XDG_CONFIG_HOME).
    • sourced_by_path: use instead of sourced_by_config if you need to specify arbitrary paths that aren’t relative to the systems config home.
    • pattern: lua regex pattern that the config files are matched against to check if they’re including the output file properly
    • line_pattern: like pattern, except the matching is done line-by-line.
    • hint: example of how to properly include the output file in the config file

niji.fs.output_unchecked(path, content)

Outputs a file to the module’s output directory without performing further checks.

If the output file is crucial for this module to function, consider using niji.fs.output_artifact instead.

The path argument for this functions is relative to your module’s output folder, which, by default, is located at ~/.local/share/niji/<module name>.

  • path: The relative path of the output file within the output folder (string)
  • content: The content to write to the file (string)
  • returns: The absolute path of the file that was written to (string)

niji.fs.get_output_dir()

Returns the directory that niji.fs.output places files into.

  • returns: the output directory

niji.fs.read_config_asset(path)

Reads a file with a path relative to .config/niji. This is often used for things like supplementary configuration files that get inserted into the generated config of a module, as used in the mako module for example.

  • path: The relative path of the asset file within the config folder (string)
  • returns: The contents of the file (string)

niji.fs.read_config(path)

Reads a file with a path relative to ~/.config.

  • path: The relative path of the config file (string)
  • returns: The contents of the file (string)

niji.fs.read_state(path)

Reads a file with a path relative to ~/.local/state.

  • path: The relative path of the state file (string)
  • returns: The contents of the file (string)

niji.fs.read_data(path)

Reads a file with a path relative to ~/.local/share.

  • path: The relative path of the state file (string)
  • returns: The contents of the file (string)

Namespace niji.mod

The namespace niji.mod can be used to obtain metadata about the current module.

niji.mod.name

The name of the current module (string)

niji.mod.path

The absolute path to the module folder of the current module (string)

Namespace niji.os

The namespace niji.os contains supplementary functions to the “os” functionality in lua.

niji.os.exec_detached(command)

Behaves like the builtin os.exec function in lua, except it detaches the command from the parent process, allowing it to keep running in the background after niji has completed execution.

You should use this method if you want to restart a background process with updated configuration, for example.

  • command: The command to execute in the background (string)

Namespace niji.util

The namespace niji.util implements functions for a couple of common, specific operations.

niji.util.font_size(config, default)

This function allows modules to easily handle the global font_scale option. If you output a font size to somewhere, simply pass it through this function to allow the user to scale their system font to their liking.

  • config: The module configuration passed to the module handlers
  • default: The font size to use if the scale is 1.0 (int)
  • returns: The properly scaled font size (int)
function M.apply(config, theme)
    local my_font_size = niji.util.font_size(config, 12)

    -- ...
end

niji.util.by_theme(theme, value)

This function makes it easy to allow a config option to optionally be set for each theme individually. The archetypical use case is modules with wallpaper support handling the global wallpaper config option.

The logic itself is fairly simple; if value is a table, return value[<theme name>], or value.default if that is not set. Otherwise, just return value itself.

  • theme: The theme passed to the apply handler
  • value: The config value to handle
function M.apply(config, theme)
    local selected_wallpaper = niji.util.by_theme(theme, config.wallpaper)

    -- ...
end

Namespace niji.xdg

The namespace niji.xdg provides bindings to the configured locations for the XDG base directories standard.

niji.xdg.config_home

$XDG_CONFIG_HOME, or $HOME/.config by default. (string)

niji.xdg.data_home

$XDG_DATA_HOME, or $HOME/.local/share by default. (string)

niji.xdg.state_home

$XDG_STATE_HOME, or $HOME/.local/state by default. (string)

niji.xdg.cache_home

$XDG_CACHE_HOME, or $HOME/.cache by default. (string)

niji.xdg.runtime_dir

The value of $XDG_RUNTIME_DIR. (string)

niji.xdg_data_dirs

The paths contained in $XDG_DATA_DIRS, or { "/usr/local/share", "/usr/share" } by default. (string[])

niji.xdg_config.dirs

The paths contained in $XDG_CONFIG_DIRS, { "/etc/xdg" } by default. (string[])

Templating reference

niji has builtin support for templating using its niji.Template API.

The templating language used for this is niji’s own dialect of mustache. You can look at the mustache documentation for general information on how it works, it mostly applies to niji’s dialect as well.

One major difference from the mustache specification is that triple mustaches ({{{name}}}), which are normally used to disable escaping of HTML characters, are not supported. Instead, niji templates just never escape HTML characters.

Custom Formats

The one extension that niji makes to the base mustache specification is custom formats for complex types. niji’s mustache dialect provides special syntax for displaying formattable types using format strings. This feature is necessary because the vast array of targets niji supports may expect vastly different formats for different data types, and it is impractical to split those data types up into more atomic parts.

For example, you can render a color using a custom format like this:

{{my_color : "🔴{r}🟢{g}🔵{b}"}}

The result of rendering this with my_color = "#abcdefff" would be 🔴171🟢205🔵239.

Often times, you will want to use a specific format for the entirety of a template. You can do this by adding a format specification for the type name at the top of your file like this:

{{% "color" : "rgba({r}, {g}, {b}, {a})" %}}

.some-class {
    background-color: {{my_color}}
}

The general format for format strings is exactly the same as that which is used by Rust’s standard library, and you can insert any of the properties defined for the type you’re working with. A list can be found in the following section.

Formattable Types

For now, the only formattable type is niji.Color. It exposes the following properties:

NameDescription
rThe red component as an integer between 0 and 255
gThe green component as an integer between 0 and 255
bThe blue component as an integer between 0 and 255
aThe alpha component as an integer between 0 and 255
rxThe red component as two hexadecimal digits
gxThe green component as two hexadecimal digits
bxThe blue component as two hexadecimal digits
axThe alpha component as two hexadecimal digits
rfThe red component as a float between 0 and 1
gfThe green component as a float between 0 and 1
bfThe blue component as a float between 0 and 1
afThe alpha component as a float between 0 and 1