From 13e366d1fe6844959905d9d06e87aae9ec32703b Mon Sep 17 00:00:00 2001 From: smgr Date: Sun, 28 Sep 2025 03:43:59 -0700 Subject: [PATCH] add minor details to usage docs --- .gitignore | 1 + README.md | 165 ++++++++-------- docs/index.md | 11 +- docs/reference/archive.md | 348 ++++++++++++++++++---------------- docs/reference/configuring.md | 169 +++++++++-------- docs/reference/usage.md | 168 +++++++++++++++- pyproject.toml | 2 +- uv.lock | 2 +- 8 files changed, 535 insertions(+), 331 deletions(-) diff --git a/.gitignore b/.gitignore index 1df09f3..7de6248 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ __pycache__/ .pytest_cache/ .python-version .venv/ +.ruff_cache/ # vendor and build files dist/ diff --git a/README.md b/README.md index 7072094..b0a0f40 100644 --- a/README.md +++ b/README.md @@ -1,63 +1,67 @@ # Symconf -`symconf` is a CLI tool for managing local application configuration. It implements a -general model that supports dynamically switching/reloading themes for any application, -and provides a basic means of templatizing your config files. +`symconf` is a CLI tool for managing local application configuration. It +implements a general model that supports dynamically switching/reloading themes +for any application, and provides a basic means of templatizing your config +files. ## Simple example Below is a simple example demonstrating two system-wide theme switches: ![Simple example](docs/_static/example.gif) -This GIF shows two `symconf` calls, the first of which applies a `gruvbox` dark theme and -the second a dark [`monobiome`][1] variant. Each call (of the form `symconf config -m dark -s -style`) indicates a dark mode preference and a particular color palette that should be -used when populating config file templates. Specifically, in this example, invoking -`symconf` results in the following app-specific config updates: +This GIF shows two `symconf` calls, the first of which applies a `gruvbox` dark +theme and the second a dark [`monobiome`][1] variant. Each call (of the form +`symconf config -m dark -s style`) indicates a dark mode preference and a +particular color palette that should be used when populating config file +templates. Specifically, in this example, invoking `symconf` results in the +following app-specific config updates: -- **GTK**: reacts to the mode setting and sets `prefer-dark` system-wide, changing general - GTK-responsive applications like Nautilus and Firefox (and subsequently websites that - are responsive to `prefers-color-scheme`) -- **kitty**: theme template is re-generated using the specified palette, and `kitty` - processes are sent a message to live-reload the new config file -- **neovim**: a `vim` theme file (along with a statusline theme) is generated from the - chosen palette, and running instances of `neovim` are sent a message to re-source this - theme (via `nvim --remote-send`) +- **GTK**: reacts to the mode setting and sets `prefer-dark` system-wide, + changing general GTK-responsive applications like Nautilus and Firefox (and + subsequently websites that are responsive to `prefers-color-scheme`) +- **kitty**: theme template is re-generated using the specified palette, and + `kitty` processes are sent a message to live-reload the new config file +- **neovim**: a `vim` theme file (along with a statusline theme) is generated + from the chosen palette, and running instances of `neovim` are sent a message + to re-source this theme (via `nvim --remote-send`) - **waybar**: bar styles are updated to match the mode setting -- **sway**: the background color and window borders are dynamically set to base palette - colors, and `swaymsg reload` is called +- **sway**: the background color and window borders are dynamically set to base + palette colors, and `swaymsg reload` is called - **fzf**: a palette-dependent theme is re-generated and re-exported -- **rofi**: launcher text and highlight colors are set according to the mode and palette, - applying on next invocation +- **rofi**: launcher text and highlight colors are set according to the mode + and palette, applying on next invocation -This example highlights the generality of `symconf`, and so long as an app's config can be -reloaded dynamically, you can use a single `symconf` call to apply themes for an arbitrary -number of apps at once. +This example highlights the generality of `symconf`, and so long as an app's +config can be reloaded dynamically, you can use a single `symconf` call to +apply themes for an arbitrary number of apps at once. # Behavior -`symconf` uses a simple operational model that symlinks centralized config files to their -expected locations across the system. This central config directory can then be version -controlled, and app config files can be updated in one place. +`symconf` uses a simple operational model that symlinks centralized config +files to their expected locations across the system. This central config +directory can then be version controlled, and app config files can be updated +in one place. -App config files can either be concrete (fully-specified) or templates (to be populated by -values conditional on style, e.g., a palette). When `symconf` is executed with a -particular mode preference (dark or light) and a style (any other indicator of thematic -elements, often simply in the form of a palette like `solarized` or `gruvbox`), it -searches for both concrete and template config files that match and symlinks them to -registered locations. When necessary, `symconf` will also match and execute scripts to -reload apps after updating their configuration. +App config files can either be concrete (fully-specified) or templates (to be +populated by values conditional on style, e.g., a palette). When `symconf` is +executed with a particular mode preference (dark or light) and a style (any +other indicator of thematic elements, often simply in the form of a palette +like `solarized` or `gruvbox`), it searches for both concrete and template +config files that match and symlinks them to registered locations. When +necessary, `symconf` will also match and execute scripts to reload apps after +updating their configuration. You can find more details on how `symconf`'s matching scheme works in [Matching](docs/reference/matching.md). # Configuring -Before using, you must first set up your config directory to house your config files and -give `symconf` something to act on. See [Configuring](docs/reference/configuring.md) for -details. +Before using, you must first set up your config directory to house your config +files and give `symconf` something to act on. See +[Configuring](docs/reference/configuring.md) for details. # Installation -The recommended way to install `symconf` is via `pipx`, which is particularly well-suited -for managing Python packages meant to be used as CLI programs. With `uv` on your system, -you can install with +The recommended way to install `symconf` is via `pipx`, which is particularly +well-suited for managing Python packages meant to be used as CLI programs. With +`uv` on your system, you can install with ```sh uv tool install symconf @@ -74,56 +78,60 @@ You can also install via `pip`, or clone and install locally. # Usage - `-h --help`: print help message - `-c --config-dir`: set the location of the `symconf` config directory -- `symconf config` is the subcommand used to match and set available config files for - registered applications - * `-a --apps`: comma-separate list of registered apps, or `"*"` (default) to consider - all registered apps. - * `-m --mode`: preferred lightness mode/scheme, either `light`, `dark`, `any`, or - `none`. - * `-s --style`: style indicator, often the name of a color palette, capturing thematic - details in a config file to be matched. `any` or `none` are reserved keywords (see - below). - * `-T --template-vars`: additional groups to use when populating templates, in the form - `=`, where `` is a template group with a folder - `$CONFIG_HOME/groups//` and `` should correspond to a TOML file in this - folder (i.e., `.toml`). -- `symconf generate` is a subcommand that can be used for batch generation of config - files. It accepts the same arguments as `symconf config`, but rather than selecting the - best match to be used for the system setting, all matching templates are generated. - There is one additional required argument: - * `-o --output-dir`: the directory under which generated config files should be written. - App-specific subdirectories are created to house config files for each provided app. +- `symconf config` is the subcommand used to match and set available config + files for registered applications + * `-a --apps`: comma-separate list of registered apps, or `"*"` (default) to + consider all registered apps. + * `-m --mode`: preferred lightness mode/scheme, either `light`, `dark`, + `any`, or `none`. + * `-s --style`: style indicator, often the name of a color palette, capturing + thematic details in a config file to be matched. `any` or `none` are + reserved keywords (see below). + * `-T --template-vars`: additional groups to use when populating templates, + in the form `=`, where `` is a template group with a + folder `$CONFIG_HOME/groups//` and `` should correspond to a + TOML file in this folder (i.e., `.toml`). +- `symconf generate` is a subcommand that can be used for batch generation of + config files. It accepts the same arguments as `symconf config`, but rather + than selecting the best match to be used for the system setting, all matching + templates are generated. There is one additional required argument: + * `-o --output-dir`: the directory under which generated config files should + be written. App-specific subdirectories are created to house config files + for each provided app. - `symconf install`: runs install scripts for matching apps that specify one - * `-a --apps`: comma-separate list of registered apps, or `"*"` (default) to consider - all registered apps. + * `-a --apps`: comma-separate list of registered apps, or `"*"` (default) to + consider all registered apps. - `symconf update`: runs update scripts for matching apps that specify one - * `-a --apps`: comma-separate list of registered apps, or `"*"` (default) to consider - all registered apps. + * `-a --apps`: comma-separate list of registered apps, or `"*"` (default) to + consider all registered apps. -The keywords `any` and `none` can be used when specifying `--mode`, `--style`, or as a -value in `--template-vars` (and we refer to each of these variables as _factors_ that help -determine a config match): +The keywords `any` and `none` can be used when specifying `--mode`, `--style`, +or as a value in `--template-vars` (and we refer to each of these variables as +_factors_ that help determine a config match): -- `any` will match config files with _any_ value for this factor, preferring config files - with a value `none`, indicating no dependence on the factor. This is the default value - when a factor is left unspecified. -- `none` will match `"none"` directly for a given factor (so no special behavior), but - used to indicate that a config file is independent of the factor. For instance, +- `any` will match config files with _any_ value for this factor, preferring + config files with a value `none`, indicating no dependence on the factor. + This is the default value when a factor is left unspecified. +- `none` will match `"none"` directly for a given factor (so no special + behavior), but used to indicate that a config file is independent of the + factor. For instance, ```sh symconf config -m light -s none ``` - will match config files that capture the notion of a light mode, but do not depend on or - provide further thematic components such as a color palette. + will match config files that capture the notion of a light mode, but do not + depend on or provide further thematic components such as a color palette. ## Examples -- Set a dark mode for all registered apps, matching any available style/palette component: +- Set a dark mode for all registered apps, matching any available style/palette + component: ```sh symconf config -m dark ``` -- Set `solarized` theme for `kitty` and match any available mode (light or dark): +- Set `solarized` theme for `kitty` and match any available mode (light or + dark): ```sh symconf config -s solarized -a kitty @@ -133,16 +141,17 @@ determine a config match): ```sh symconf config -m dark -s gruvbox -apps="kitty,nvim" ``` -- Set a dark `gruvbox` theme for all apps, and attempt to match other template elements: +- Set a dark `gruvbox` theme for all apps, and attempt to match other template + elements: ```sh symconf config -m dark -s gruvbox -T font=mono window=sharp ``` which would attempt to find and load key-value pairs in the files - `$CONFIG_HOME/groups/font/mono.toml` and `$CONFIG_HOME/groups/window/sharp.toml` to be - used as values when filling templatized config files. - + `$CONFIG_HOME/groups/font/mono.toml` and + `$CONFIG_HOME/groups/window/sharp.toml` to be used as values when filling + templatized config files. [1]: https://github.com/ologio/monobiome diff --git a/docs/index.md b/docs/index.md index 9a93d92..fc1bbb8 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,10 +11,11 @@ :recursive: symconf.config - symconf.template - symconf.matching symconf.reader symconf.runner + symconf.matching + symconf.template + symconf.util ``` ## Auto-reference contents @@ -28,10 +29,10 @@ _autoref/symconf.rst :maxdepth: 2 :caption: Contents -reference/configuring -reference/usage reference/archive -reference/documentation/index +reference/configuring +reference/matching +reference/usage ``` ```{include} ../README.md diff --git a/docs/reference/archive.md b/docs/reference/archive.md index d0597c0..04540a8 100644 --- a/docs/reference/archive.md +++ b/docs/reference/archive.md @@ -1,80 +1,89 @@ # Archive -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. +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 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 +- **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: +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. +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 `--.`. 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 `-.`, where `tone4-light` is the -provided theme name.) +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 +`--.`. 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 `-.`, 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: +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. +- 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. +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: +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: +- When setting a theme for a particular app, the following variables will be + available: * `` * `` * `` - For apps with `external_theme = False`, config variants must named as - `--.`, where `` is the app's default config file - extension. -- For apps with `external_theme = True`, the file `/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. + `--.`, where `` is the app's default + config file extension. +- For apps with `external_theme = True`, the file + `/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 @@ -87,147 +96,162 @@ appropriately: ## Directory structure - `autoconf/`: 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 - * `/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. - + `/apps//templates/`: houses the TOML maps for the color - palette `` under app ``. Files `.toml` will be mapped to - `.conf` in the theme output folder (below), so ensure the naming - standards align with those outlined above. - + `/apps//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. + * `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 + * `/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. + + `/apps//templates/`: houses the TOML maps for the + color palette `` under app ``. Files + `.toml` will be mapped to `.conf` in the theme output + folder (below), so ensure the naming standards align with those + outlined above. + + `/apps//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 ` , 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 `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 +- Applies to specific app with `-a ` , 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 `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. -`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. -- 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 `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. +`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--` call; suppose we're -currently running the dark scheme (see first image) and I run `make set-tone4-light`: +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--` 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). + 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).)_ +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 +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: + 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). + _(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`: + 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: + 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/autoconf/autoconf/themes/tone4/apps/kitty/generated/light.conf + .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). -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`. + 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 + ](_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: + _(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)_ diff --git a/docs/reference/configuring.md b/docs/reference/configuring.md index 957c5ba..b257e91 100644 --- a/docs/reference/configuring.md +++ b/docs/reference/configuring.md @@ -1,61 +1,64 @@ # Configuring -`symconf` operates on a central directory that houses all of the config files you may wish -to apply. The default location for this directory is your `$XDG_CONFIG_HOME` (e.g., -`~/.config/symconf/`), but it can be any location on your system so long as it's specified -(see more in Usage). +`symconf` operates on a central directory that houses all of the config files +you may wish to apply. The default location for this directory is your +`$XDG_CONFIG_HOME` (e.g., `~/.config/symconf/`), but it can be any location on +your system so long as it's specified (see more in Usage). -`symconf` expects you to create two top-level components in your config directory: an -`apps/` directory and an `app_registry.toml` file. +`symconf` expects you to create two top-level components in your config +directory: an `apps/` directory and an `app_registry.toml` file. **High-level view**: - `symconf` operates on a single directory that houses all your config files -- Config files in this directory must be placed under an `apps//` folder to be - associated with the app `` -- For apps to be visible, you need an `app_registry.toml` file that tells `symconf` where - to symlink your files in `apps/` +- Config files in this directory must be placed under an `apps//` + folder to be associated with the app `` +- For apps to be visible, you need an `app_registry.toml` file that tells + `symconf` where to symlink your files in `apps/` ## Apps directory An `apps/` directory should be created in your config home, with a subdirectory -`apps//` for each app with config files that you'd like to be visible to -`symconf`. Note that simply populating an app's config folder here will do nothing on its -own; the app must also have been registered (discussed in item #2) in order for these -files to be used when `symconf` is invoked. (This just means you can populate your `apps/` -folder safely without expecting any default behavior. More often than not you'll be -expected to tell `symconf` exactly where your config files should end up, meaning you know -exactly what it's doing.) +`apps//` for each app with config files that you'd like to be visible +to `symconf`. Note that simply populating an app's config folder here will do +nothing on its own; the app must also have been registered (discussed in item +#2) in order for these files to be used when `symconf` is invoked. (This just +means you can populate your `apps/` folder safely without expecting any default +behavior. More often than not you'll be expected to tell `symconf` exactly +where your config files should end up, meaning you know exactly what it's +doing.) ### User config -Inside your app-specific subdirectory, your managed config files should be placed in a -`user/` subdirectory (distinguishing them from those generated by templates; see more -in Themes). Your config files themselves are then expected to follow a specific naming -scheme: +Inside your app-specific subdirectory, your managed config files should be +placed in a `user/` subdirectory (distinguishing them from those generated by +templates; see more in Themes). Your config files themselves are then expected +to follow a specific naming scheme: ```sh -. ``` -This ties your config file to a particular theme setting as needed, and `symconf` will -apply it if it matches the theme setting you provide when invoked. The specific values are -as follows: +This ties your config file to a particular theme setting as needed, and +`symconf` will apply it if it matches the theme setting you provide when +invoked. The specific values are as follows: -- `scheme`: can be `light`, `dark`, or `none`. Indicates whether the config file should - be applied specifically when requesting a light or dark mode. Use `none` to indicate - that the config file does not have settings specific to a light/dark mode. -- `palette`: a "palette name" of your choosing, or `none`. The palette name you use - here may refer specifically to a color palette used by the config file, but can be - used generally to indicate any particular group of config settings (e.g., fonts, - transparency, etc). Use `none` to indicate that the file does not correspond to any - particular style group. -- `config-name`: the _name_ of the config file. This should correspond to _same path - name_ that is expected by the app being configured. For example, if your app expects a - config file at `a/b/c/d.conf`, "`d.conf`" is the path name. +- `scheme`: can be `light`, `dark`, or `none`. Indicates whether the config + file should be applied specifically when requesting a light or dark mode. Use + `none` to indicate that the config file does not have settings specific to a + light/dark mode. +- `palette`: a "palette name" of your choosing, or `none`. The palette name you + use here may refer specifically to a color palette used by the config file, + but can be used generally to indicate any particular group of config settings + (e.g., fonts, transparency, etc). Use `none` to indicate that the file does + not correspond to any particular style group. +- `config-name`: the _name_ of the config file. This should correspond to _same + path name_ that is expected by the app being configured. For example, if your + app expects a config file at `a/b/c/d.conf`, "`d.conf`" is the path name. -When invoking `symconf` with specific scheme and palette settings (see more in Usage), -appropriate config files can be matched based on how you've named your files. +When invoking `symconf` with specific scheme and palette settings (see more in +Usage), appropriate config files can be matched based on how you've named your +files. -For example, suppose I want to set up a simple light/dark mode switch for the `kitty` -terminal emulator. The following tree demonstrates a valid setup: +For example, suppose I want to set up a simple light/dark mode switch for the +`kitty` terminal emulator. The following tree demonstrates a valid setup: ```sh @@ -66,30 +69,31 @@ terminal emulator. The following tree demonstrates a valid setup: └── none-dark.kitty.conf ``` -where `none-light.kitty.conf` may set a light background and `none-dark.kitty.conf` a dark -one. `none` is used for the `` part of the name to indicate the configuration does -not pertain to any specific palette and can be matched even if one is not provided. With -an appropriate `app_regsitry.toml` file (see below), invoking +where `none-light.kitty.conf` may set a light background and +`none-dark.kitty.conf` a dark one. `none` is used for the `` part of +the name to indicate the configuration does not pertain to any specific palette +and can be matched even if one is not provided. With an appropriate +`app_regsitry.toml` file (see below), invoking ```sh symconf --theme=light --apps=kitty ``` -would symlink `$XDG_CONFIG_HOME/symconf/apps/kitty/user/none-light.kitty.conf` to -`~/.config/kitty/kitty.conf`. +would symlink `$XDG_CONFIG_HOME/symconf/apps/kitty/user/none-light.kitty.conf` +to `~/.config/kitty/kitty.conf`. ### Templatized config -Note the potential inconvenience in needing to manage two separate config files in the -above example, very likely with all but one line of difference. Templating enables -populating config template files dynamically with theme-specific variables of your -choosing. - +Note the potential inconvenience in needing to manage two separate config files +in the above example, very likely with all but one line of difference. +Templating enables populating config template files dynamically with +theme-specific variables of your choosing. ### Reload scripts -After symlinking a new set of config files, it is often necessary to reload the system or -relevant apps in order for the new config settings to apply. Within an app's subdirectory, -a `call/` folder can be created to hold scripts that should apply based on certain schemes -or palettes (matching them in the same way as config files). For example, +After symlinking a new set of config files, it is often necessary to reload the +system or relevant apps in order for the new config settings to apply. Within +an app's subdirectory, a `call/` folder can be created to hold scripts that +should apply based on certain schemes or palettes (matching them in the same +way as config files). For example, ```sh @@ -99,22 +103,22 @@ or palettes (matching them in the same way as config files). For example, └── none-none.sh ``` -`none-none.sh` might simply contain `kill -s USR1 $(pgrep kitty)`, which is a way to tell -all running `kitty` instances to reload their config settings. Again, following the naming -scheme for config files, a script named `none-none.sh` will apply under any scheme or -palette specification. Thus, in our light/dark mode switch example, invoking `symconf ---theme=light --apps=kitty` would: +`none-none.sh` might simply contain `kill -s USR1 $(pgrep kitty)`, which is a +way to tell all running `kitty` instances to reload their config settings. +Again, following the naming scheme for config files, a script named +`none-none.sh` will apply under any scheme or palette specification. Thus, in +our light/dark mode switch example, invoking `symconf --theme=light +--apps=kitty` would: 1. Search and match the config name `none-light.kitty.conf` and symlink it to `~/.config/kitty/kitty.conf`. -2. Search and match `none-none.sh` and execute it, applying the new light mode settings to - all running `kitty` instances. - +2. Search and match `none-none.sh` and execute it, applying the new light mode + settings to all running `kitty` instances. ## App registry -An `app_registry.toml` file, used to specify the target locations for app-specific -config files. To "register" an app, you simply need to add the following text block to -the `app_registry.toml` file: +An `app_registry.toml` file, used to specify the target locations for +app-specific config files. To "register" an app, you simply need to add the +following text block to the `app_registry.toml` file: ```toml [app.] @@ -128,22 +132,22 @@ config_map = { } ``` -(Note that text in angle brackets refers to values that should be replaced.) This tells -`symconf` how it should handle each app's config files. The `` (e.g., -`kitty`) should correspond to a subdirectory under `apps/` (e.g., `apps/kitty/`) that -holds your config files for that app. As shown, you then need to supply either of the -following options: +(Note that text in angle brackets refers to values that should be replaced.) +This tells `symconf` how it should handle each app's config files. The +`` (e.g., `kitty`) should correspond to a subdirectory under `apps/` +(e.g., `apps/kitty/`) that holds your config files for that app. As shown, you +then need to supply either of the following options: -- `config_dir`: specifies a single directory where all of the app's matching config - files should be symlinked. In the `kitty` example, this might be `~/.config/kitty`. - This is the simplest and most common option provided most apps expect all of their - config files to be in a single directory. -- `config_map`: a dictionary mapping config file _path names_ to the _exact paths_ that - should be created during the symlink process. This is typically needed when an app - has many config files that need to be set in several disparate locations across your - system. In the `kitty` example, although not necessary (and in general you should - prefer to set `config_dir` when applicable), we could have the following - `config_map`: +- `config_dir`: specifies a single directory where all of the app's matching + config files should be symlinked. In the `kitty` example, this might be + `~/.config/kitty`. This is the simplest and most common option provided most + apps expect all of their config files to be in a single directory. +- `config_map`: a dictionary mapping config file _path names_ to the _exact + paths_ that should be created during the symlink process. This is typically + needed when an app has many config files that need to be set in several + disparate locations across your system. In the `kitty` example, although not + necessary (and in general you should prefer to set `config_dir` when + applicable), we could have the following `config_map`: ```toml [app.kitty] @@ -152,8 +156,9 @@ following options: } ``` - This tells `symconf` to symlink the exact location `~/.config/kitty/kitty.conf` to - the matching `kitty.conf` under the `apps/kitty` directory. + This tells `symconf` to symlink the exact location + `~/.config/kitty/kitty.conf` to the matching `kitty.conf` under the + `apps/kitty` directory. ## Directory structure In total, the structure of your base config directory can look as follows: diff --git a/docs/reference/usage.md b/docs/reference/usage.md index 808059c..64f6f97 100644 --- a/docs/reference/usage.md +++ b/docs/reference/usage.md @@ -1,6 +1,170 @@ # Usage -```{toctree} -:hidden: +```sh +usage: symconf [-h] [-c CONFIG_DIR] [-v] {config,generate,install,update} ... +Manage application configuration with symlinks. + +options: + -h, --help show this help message and exit + -c CONFIG_DIR, --config-dir CONFIG_DIR + Path to config directory + -v, --version Print symconf version + +subcommand actions: + {config,generate,install,update} ``` + +Additional argument details: + +- `-h --help`: print help message +- `-c --config-dir`: the location of the `symconf` config directory. Assumes + `$XDG_CONFIG_HOME` (e.g., `~/.config/symconf/`) by default. + +## `config` subcommand +The config subcommand applies symlinks for registered application routes that +meet specified constraints. + +```sh +usage: symconf config [-h] [-s STYLE] [-m MODE] [-a APPS] [-T TEMPLATE_VARS [TEMPLATE_VARS ...]] + +Set config files for registered applications. + +options: + -h, --help show this help message and exit + -s STYLE, --style STYLE + Style indicator (often a color palette) capturing thematic details in a config file + -m MODE, --mode MODE Preferred lightness mode/scheme, either "light," "dark," "any," or "none." + -a APPS, --apps APPS Application target for theme. App must be present in the registry. Use "*" to apply to all registered apps + -T TEMPLATE_VARS [TEMPLATE_VARS ...], --template-vars TEMPLATE_VARS [TEMPLATE_VARS ...] + Groups to use when populating templates, in the form group=value +``` + +- `symconf config` is the subcommand used to match and set available config + files for registered applications + * `-a --apps`: comma-separate list of registered apps, or `"*"` (default) to + consider all registered apps. + * `-m --mode`: preferred lightness mode/scheme, either `light`, `dark`, + `any`, or `none`. + * `-s --style`: style indicator, often the name of a color palette, capturing + thematic details in a config file to be matched. `any` or `none` are + reserved keywords (see below). + * `-T --template-vars`: additional groups to use when populating templates, + in the form `=`, where `` is a template group with a + folder `$CONFIG_HOME/groups//` and `` should correspond to a + TOML file in this folder (i.e., `.toml`). + + +## `generate` subcommand +The generate subcommand fills in templates with theme values matched under +provided constraints, + +```sh +usage: symconf generate [-h] -o OUTPUT_DIR [-s STYLE] [-m MODE] [-a APPS] [-T TEMPLATE_VARS [TEMPLATE_VARS ...]] + +Generate all template config files for specified apps + +options: + -h, --help show this help message and exit + -o OUTPUT_DIR, --output-dir OUTPUT_DIR + Path to write generated template files + -s STYLE, --style STYLE + Style indicator (often a color palette) capturing thematic details in a config file + -m MODE, --mode MODE Preferred lightness mode/scheme, either "light," "dark," "any," or "none." + -a APPS, --apps APPS Application target for theme. App must be present in the registry. Use "*" to apply to all registered apps + -T TEMPLATE_VARS [TEMPLATE_VARS ...], --template-vars TEMPLATE_VARS [TEMPLATE_VARS ...] + Groups to use when populating templates, in the form group=value +``` + +- `symconf generate` is a subcommand that can be used for batch generation of + config files. It accepts the same arguments as `symconf config`, but rather + than selecting the best match to be used for the system setting, all matching + templates are generated. There is one additional required argument: + * `-o --output-dir`: the directory under which generated config files should + be written. App-specific subdirectories are created to house config files + for each provided app. + +## `install` subcommand +The install subcommand runs the `install.sh` scripts for registered apps. + +```sh +usage: symconf install [-h] [-a APPS] + +Run install scripts for registered applications. + +options: + -h, --help show this help message and exit + -a APPS, --apps APPS Application target for theme. App must be present in the registry. Use "*" to apply to all registered apps +``` + +- `symconf install`: runs install scripts for matching apps + * `-a --apps`: comma-separate list of registered apps, or `"*"` (default) to + consider all registered apps. + +## `update` subcommand +The update subcommand runs the `update.sh` scripts for registered apps. This +action expects the install process for each matched app to have been run +beforehand. + +```sh +usage: symconf update [-h] [-a APPS] + +Run update scripts for registered applications. + +options: + -h, --help show this help message and exit + -a APPS, --apps APPS Application target for theme. App must be present in the registry. Use "*" to apply to all registered apps +``` + +- `symconf update`: runs update scripts for matching apps that specify one + * `-a --apps`: comma-separate list of registered apps, or `"*"` (default) to + consider all registered apps. + +## Matching factors +The keywords `any` and `none` can be used when specifying `--mode`, `--style`, +or as a value in `--template-vars` (and we refer to each of these variables as +_factors_ that help determine a config match): + +- `any` will match config files with _any_ value for this factor, preferring + config files with a value `none`, indicating no dependence on the factor. + This is the default value when a factor is left unspecified. +- `none` will match `"none"` directly for a given factor (so no special + behavior), but used to indicate that a config file is independent of the + factor. For instance, + + ```sh + symconf config -m light -s none + ``` + + will match config files that capture the notion of a light mode, but do not + depend on or provide further thematic components such as a color palette. + +## Examples +- Set a dark mode for all registered apps, matching any available style/palette + component: + + ```sh + symconf config -m dark + ``` +- Set `solarized` theme for `kitty` and match any available mode (light or + dark): + + ```sh + symconf config -s solarized -a kitty + ``` +- Set a dark `gruvbox` theme for multiple apps (but not all): + + ```sh + symconf config -m dark -s gruvbox -apps="kitty,nvim" + ``` +- Set a dark `gruvbox` theme for all apps, and attempt to match other template + elements: + + ```sh + symconf config -m dark -s gruvbox -T font=mono window=sharp + ``` + + which would attempt to find and load key-value pairs in the files + `$CONFIG_HOME/groups/font/mono.toml` and + `$CONFIG_HOME/groups/window/sharp.toml` to be used as values when filling + templatized config files. diff --git a/pyproject.toml b/pyproject.toml index d2fce3f..c64c927 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "symconf" -version = "0.8.2" +version = "0.8.3" description = "Local app configuration manager" requires-python = ">=3.12" authors = [ diff --git a/uv.lock b/uv.lock index 3a3eee9..7aea322 100644 --- a/uv.lock +++ b/uv.lock @@ -529,7 +529,7 @@ wheels = [ [[package]] name = "symconf" -version = "0.8.2" +version = "0.8.3" source = { editable = "." } dependencies = [ { name = "colorama" },