3. Packages and `local.toml` - SuperCuber/dotter GitHub Wiki

Defining packages in global.toml

Dotter supports modular configuration through packages. A package is a self-contained set of files and variables that can be reused across different machines.

A package has several properties, and each of them is optional.

Files

The files section is a mapping between the path of the file relative to the repository root, and its location in the filesystem (where the program expects it)

In the example from the Getting Started page, say your repository is at ~/.dotfiles, it will map ~/.dotfiles/zshrc to ~/.zshrc, and ~/.dotfiles/vimrc to ~/.vimrc

On Windows, ~ is expanded to C:\Users\<USERNAME>\, and / are interpreted as folder separators.

For advanced uses, read more about Complex Targets

Variables

Variables defined in an enabled package become available to use in templated files. Variables of all types are supported:

[mypackage.variables]
my_int = 5
my_favorite_color = "red"
my_font = { font = "Fira Code", size = 20, color = "#ffffff" }
cool_things = ["linux", "dotter"]

Variables belong under a specific package, but are available to templated files from all the other packages as well.

Dotter also supports several Builtin Variables

Depends

Packages can depend on each other. If a package is enabled, all of the depended packages will be recursively enabled as well.

For example, you can have a graphics package that defines a font size or colorscheme, and packages for your terminal or window manager can both depend on it like so:

[xfce4_terminal]
depends = ["graphics"]

[xfce4_terminal.files]
xfce4_terminal = "~/.config/xfce4/terminal/terminalrc"

[i3]
depends = ["graphics"]

[i3.files]
i3 = "~/.i3/config"

[graphics.variables]
font_size = 20
text_color = "#ffffff"

local.toml

The local.toml file contains configuration specific to the machine. Let's follow along this example, used together with the previous global.toml:

# local.toml can "include" another file - more on this in the next section.
includes = [".dotter/linux.toml"]

# An array of the names of all packages that are selected.
# Only the files and variables that belong to packages in this list are kept.
# Note that in this example, the `graphics` package is automatically added as well, since `i3` depends on it.
packages = ["i3"]

# File target locations can be overridden in local.toml
# This can be useful for example for applications which read from a different location depending on the platform.
# Disabling files is possible by setting them to the special value "".
[files]
Xinitrc = "~/.my_Xinitrc"
polybar = ""

# Any variables defined in local.toml override variables in global.toml
[variables]
network_interface = "wlan0"
screen_size = "1920x1080"
terminal = "xfce4-terminal"
font_size = 18

Included files and configuration merging

In local.toml, you can specify a list of files to include. included.toml looks similar to a global.toml:

[zsh.files]
zshrc = "~/.another_location"

[zsh.variables]
prompt_color = "#0000FF"

The files are loaded and merged in the following order:

  • First, all the packages from global.toml are loaded
  • Then, each package is merged with the included files, in order of appearance
    • The last time each key is set is the one that will win. So included.toml will override a file or variable set in global.toml or a previous include file
  • Then, only the packages that are in local.toml's packages variable and their dependencies are kept
  • Then, all the packages are merged into one - at this point, there mustn't be any file/variable clashes between the packages
  • Then, the merged "package" is once again merged with local.toml's contents - local.toml wins any clashes.

Why is this useful? Say, for example, you want an OS-specific configuration - maybe a program reads a file from a different location depending on the OS. (I'll use neovim as an example)

In that case, you could define global.toml like this:

[vim.files]
# This is the location for Linux
vimrc = "~/.config/nvim/init.vim"

windows.toml like this:

[vim.files]
# This is the location for Windows
vimrc = "~/AppData/Local/nvim/init.vim"

And then, on Windows you could include windows.toml like this:

includes = [".dotter/windows.toml"]
packages = ["vim"]

This will load the default linux location, then override it with the windows location, and then only deploy the file if you've selected the package.
windows.toml could contain the windows-specific tweaks of all of your packages.
If you wanted some of the settings from windows.toml but then override the rest you could do that as well - the possibilities are limitless.

⚠️ **GitHub.com Fallback** ⚠️