3. Packages and `local.toml` - SuperCuber/dotter GitHub Wiki
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.
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 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
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"
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
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 inglobal.toml
or a previous include file
- The last time each key is set is the one that will win. So
- Then, only the packages that are in
local.toml
'spackages
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.