autoconf | ||
docs | ||
tests | ||
.gitignore | ||
LICENSE | ||
Makefile | ||
pyproject.toml | ||
README.md | ||
REFACTOR.md | ||
TODO.md |
autoconf
The autoconf
project is an attempt at wrangling the complexity of configuring many
applications across one's Linux system. It provides a simple operational model for pulling
many application config files into one place, as well as generating/setting color schemes
across apps.
Quick terminology rundown for theme-related items:
- Theme: loose term referring generally to the overall aesthetic of a visual setting.
Ignoring stylistic changes (only applicable to some apps; example here might be a
a particular setting of the
waybar
layout), a theme is often just the wrapper term for a choice of color palette and scheme. For example, "tone4-light" could be a theme setting for an app likekitty
, referring to both a palette and scheme. - Palette: a set of base colors used to style text or other aspects of an app's displayed assets
- Scheme: an indication of lightness, typically either "light" or "dark.
As far as managing settings across apps, there are current two useful classifications here:
- Inseparable from theme: some apps (e.g.,
sway
,waybar
) have color scheme components effectively built in to their canonical configuration file. This can make it hard to set themes dynamically, as it would likely require some involved matching/substitution rules. This is not a level of complexity I'm willing to embrace, so we simply split the config files according to theme and/or scheme. - Can load an external theme file: some apps (e.g.,
kitty
) have a clear mechanism for loading themes. This typically implies some distinct color format, although usually somewhat easy to generate (don't have to navigate non-color settings, for instance). Such apps allow for an even less "invasive" config swapping process when setting a new theme, as one can just swap out the external theme file.
To be clear on operation implications here: apps of type (1) must have manually
maintained config variations according the desired themes. General theme settings must
follow the naming scheme <app-name>-<palette>-<scheme>.<ext>
. For example, if I wanted to set
sway
to a light variation (which, at the time of writing, would just entail changing a
single background color), I must have explicitly created a sway-tone4-light.conf
file
that captures this setting. The canonical config file will then be symlinked to the
theme-specific file when the theme is set. (Note that the palette in this example is pretty much
irrelevant, but it needs to be present in order to match the overarching setting; here you
can just think of the format being <app-name>-<theme>.<ext>
, where tone4-light
is the
provided theme name.)
For apps of type (2), the canonical config file can remain untouched so long as it refers
to a fixed, generic theme file. For example, with kitty
, my config file can point to a
current-theme.conf
file, which will be symlinked to a specific theme file here in
autoconf
when a change is requested. This enables a couple of conveniences:
- The true config directory on disk remains unpolluted with theme variants.
- If the set theme is regenerated, there is no intervention necessary to propagate its changes to the target app. The symlinked file itself will be updated when the theme does, ensuring the latest theme version is always immediately available and pointed to by the app.
Keep in mind that some apps may fall into some grey area here, allowing some external customization but locking down other settings internally. In such instances, there's no need to overcomplicate things; just stick to explicit config variants under the type (1) umbrella. Type (2) only works for generated themes anyhow; even if the target app can load an external theme, type (1) should be used if preset themes are fixed.
Naming standards
To keep things simple, we use a few fixed naming standards for setting app config files
and their themed counterparts. The app registry requires each theme-eligible app to
provide a config directory (config_dir
), containing some canonical config file
(config_file
) and to serve as a place for theme-specific config variations. The
following naming schemes must be used in order for theme switching to behave
appropriately:
-
When setting a theme for a particular app, the following variables will be available:
<app-name>
<palette>
<scheme>
-
For apps with
external_theme = False
, config variants must named as<app-name>-<palette>-<scheme>.<ext>
, where<ext>
is the app's default config file extension. -
For apps with
external_theme = True
, the file<config-dir>/current-theme.conf
will be used when symlinking the requested theme. The config file thus must point to this file in order to change with the set theme.Additionally, the theme symlink will be created from the file
<autoconf-root>/autoconf/themes/<palette>/apps/<app-name>/generated/<scheme>.conf
to
<config-dir>/current-theme.conf
.
Directory structure
autoconf/
: main repo directoryconfig/
: app-specific configuration files. Each folder inside this directory is app-specific, and the target of associated copy operations when a config sync is performed. Nothing in this directory should pertain to any repo functionality; it should only contain config files that originated elsewhere on the system.themes/
: app-independent theme data files. Each folder in this directory should correspond to a specific color palette and house any relevant color spec files (currently likely be acolors.json
). Also servers the output location for generated theme files<palette>/colors.json
: JSON formatted color key-value pairings for palette colors. There's no standard here aside from the filename and format; downstream app-specific TOML templates can be dependent on any key naming scheme within the JSON.
<palette>/apps/<app-name>/templates/
: houses the TOML maps for the color palette<palette>
under app<app-name>
. Files<fname>.toml
will be mapped to<fname>.conf
in the theme output folder (below), so ensure the naming standards align with those outlined above.<palette>/apps/<app-name>/generated/
: output directory for generated scheme variants. These are the symlink targets for dynamically set external themes.
app_registry.toml
: global application "registry" used by sync and theme-setting scripts. This lets apps be dynamically added or removed from being eligible for config-related operations.
Scripts
set_theme.py
: sets a theme across select apps.
- Applies to specific app with
-a <app>
, or to all apps in theapp_registry.toml
with-a "*"
. - Uses symlinks to set canonical config files to theme-based variations. Which files get
set depends on the app type (see above), which really just boils down to whether
theming (1) can be specified with an external format, and (2) if it depends on
auto-generated theme files from within
autoconf
. - Palette and scheme are specified as expected. They are used to infer proper paths according to naming and structure standards.
- Real config files will never be overwritten. To begin setting themes with the script, you must delete the canonical config file expected by the app (and specified in the app registry) to allow the first symlink to be set. From there on out, symlinks will be automatically flushed.
- A report will be provided on which apps were successfully set to the requested theme, along with the file stems. A number of checks are in place for the existence of involved files and directories. Overall, the risk of overwritting a real config file is low; we only flush existing symlinks, and if the would-be target for the requested theme (be it from an auto-generated theme file, or from a manually manage config variant) doesn't exist, that app's config will be completed skipped. Essentially, everything must be in perfect shape before the symlink trigger is officially pulled.
gen_theme.py
: generates theme files for palettes by mapping their color definitions
through app-specific templates. These templates specific how to relate an app's theme
variables to the color names provided by the template.
- An app and palette are the two required parameters. If no template or output paths are provided, they will be inferred according to the theme path standards seen above.
- The
--template
argument can be a directory or a file, depending on what theme files you'd like to render. - The
--output
path, if specified, must be a directory. Generated theme files take on a name with the same stem as their source template, but using the.conf
extension. - The TOML templates should make config variable names to JSON dot-notation accessors. If color definitions are nested, the dot notation should be properly expanded by the script when mapping the colors to keyword values.
- There are a number of checks for existing paths, even those inferred (e.g., template and
output) from the palette and app. If the appropriate setup hasn't been followed, the
script will fail. Make sure the
theme
folder in question and it's nestedapp
directory are correctly setup before running the script. (Perhaps down the line there are some easy auto-setup steps to take here, but I'm not making that jump now.) - TODO: open up different app "writers," or make it easy to extend output syntax based on the app in question. This would like be as simple as mapping app names to line-generating functions, which accept the keyword and color (among other items). This can be fleshed out as needed.
sync.sh
: copies relevant configuration files from local paths into the autoconf
subpath. Markdown files in the docs directory then reference the local copies of these
files, meaning the documentation updates dynamically when the configuration files do. That
is, the (possibly extracted) config snippets will change with the current state of my
system config without any manual intervention of the documentation files.
Specific theme-setting example
To make clear how the theme setting script works on my system, the following breaks down
exactly what steps are taken to exert as much scheme control as possible. Everything at this
point is wrapped up in a single make set-<palette>-<scheme>
call; suppose we're
currently running the dark scheme (see first image) and I run make set-tone4-light
:
(Starting point; have a GTK app (GNOME files), kitty
, and Firefox (with the
system-dependent default theme set). In Firefox, I have open localsys
with its
scheme-mode to set to "auto," which should reflect the theme setting picked up by the
browser (and note the white tab icon).)
-
set_theme.py
is invoked. Global settings are applied first, based on my OS (Linux
), which callsgsettings set org.gnome.desktop.interface color-scheme 'prefer-light'
controlling settings for GTK apps and other
desktop-portal
-aware programs. This yields the following:(Portal-aware apps changed, config apps not yet set. Scheme-aware sites are updated without page refresh.)
-
Specific application styles are set. For now the list is small, including
kitty
,waybar
, andsway
.kitty
is the only type (2) application here, whereas the other two are type (1).a. For the type (1) apps, the canonical config files as specified in the app registry are symlinked to their light variants. For
sway
, this is~/.config/sway/config
, and if we look at thefile
:.config/sway/config: symbolic link to ~/.config/sway/sway-tone4-light
b. For the type (2) apps, just the
current-theme.conf
file is symlinked to the relevant palette-scheme file.kitty
is such an app, with a supported theme file fortone4
, and those files have been auto-generated viagen_theme.py
. Looking at this file under thekitty
config directory:.config/kitty/current-theme.conf: symbolic link to ~/Documents/projects/autoconf/autoconf/themes/tone4/apps/kitty/generated/light.conf
The
kitty.conf
file isn't changed, as all palette-related items are specified in the theme file. (Note that the general notion of a "theme" could include changes to other stylistic aspects, like the font family; this would likely require some hybrid type 1-2 approach not yet implemented). -
Live application instances are reloaded, according to the registered
refresh_cmd
s. Here the apps with style/config files set in step (2) are reloaded to reflect those changes. Again, in this example, this iskitty
,sway
, and thewaybar
.(Final light setting: portal-dependent apps and config-based apps changed)
-
set_theme.py
provides a report for the actions taken; in this case, the following was printed: