234 lines
13 KiB
Markdown
234 lines
13 KiB
Markdown
|
# local-config
|
||
|
The `local-config` 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 like `kitty`, 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:
|
||
|
|
||
|
1. **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.
|
||
|
2. **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
|
||
|
`local-config` 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
|
||
|
|
||
|
```
|
||
|
<local-config-root>/local-config/themes/<palette>/apps/<app-name>/generated/<scheme>.conf
|
||
|
```
|
||
|
|
||
|
to `<config-dir>/current-theme.conf`.
|
||
|
|
||
|
## Directory structure
|
||
|
|
||
|
- `local-config/`: main repo directory
|
||
|
* `config/`: 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 a `colors.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 the `app_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 `local-config`.
|
||
|
- 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 nested `app`
|
||
|
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 `local-config`
|
||
|
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).
|
||
|
](_static/set-theme-1.png)
|
||
|
|
||
|
_(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).)_
|
||
|
|
||
|
1. `set_theme.py` is invoked. Global settings are applied first, based on my OS (`Linux`),
|
||
|
which calls
|
||
|
|
||
|
```
|
||
|
gsettings 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](_static/set-theme-2.png)
|
||
|
|
||
|
_(Portal-aware apps changed, config apps not yet set. Scheme-aware sites are updated
|
||
|
without page refresh.)_
|
||
|
2. Specific application styles are set. For now the list is small, including `kitty`,
|
||
|
`waybar`, and `sway`. `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 the `file`:
|
||
|
|
||
|
```sh
|
||
|
.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
|
||
|
for `tone4`, and those files have been auto-generated via `gen_theme.py`. Looking at
|
||
|
this file under the `kitty` config directory:
|
||
|
|
||
|
```sh
|
||
|
.config/kitty/current-theme.conf: symbolic link to ~/Documents/projects/local-config/local-config/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).
|
||
|
3. 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 is `kitty`, `sway`, and the `waybar`.
|
||
|
|
||
|
![Final light setting: portal-dependent apps _and_ config-based apps changed](_static/set-theme-3.png)
|
||
|
|
||
|
_(Final light setting: portal-dependent apps _and_ config-based apps changed)_
|
||
|
4. `set_theme.py` provides a report for the actions taken; in this case, the following was
|
||
|
printed:
|
||
|
|
||
|
![`set_theme.py` output](_static/set-theme-4.png)
|
||
|
_(`set_theme.py` output)_
|