commit 5da45c97d84aa164bb3e7e40bd722f0ef586110e Author: Sam G. Date: Fri Apr 19 15:50:31 2024 -0700 initial commit (post-repo scrub) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..98d3626 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +docs/_build +.python-version diff --git a/README.md b/README.md new file mode 100644 index 0000000..2f7ff1d --- /dev/null +++ b/README.md @@ -0,0 +1,233 @@ +# 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 `--.`. 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 +`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: + * `` + * `` + * `` +- 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. + + Additionally, the theme symlink will be created from the file + + ``` + /local-config/themes//apps//generated/.conf + ``` + + to `/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 + * `/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 `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--` 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)_ diff --git a/autoconf/app_registry.toml b/autoconf/app_registry.toml new file mode 100644 index 0000000..00c39fd --- /dev/null +++ b/autoconf/app_registry.toml @@ -0,0 +1,42 @@ +# App registry -- apps eligible for theme switching +# +# Each app must be register under the "app" directive, i.e., as "[app.]" +# +# Option details: +# - external_theme: if False (default), indicates an app of type 1 as per the README. That +# is, an external theme file cannot be used, and theme switching will involve switch the +# canonical config setting. If True, the app's theme can be set through an external theme +# file. +# - support_os: OSes that support theme switching according to the implemented paths. +# Accepts a list of `uname -s` strings to match system. +# - refresh_cmd: a command to run for live refreshing the application's color scheme after +# it's been set for running instances. +# +# Default example +# [app.default] +# external_theme = False +# config_dir = '~/.config/default/' +# config_file = 'default.conf' +# refresh_cmd = 'app reload-config' +# + +[app.kitty] +external_theme = true +config_dir = '~/.config/kitty/' +config_file = 'kitty.conf' +supported_oses = ['Linux', 'Darwin'] +refresh_cmd = 'kill -s USR1 $(pgrep kitty)' + +[app.sway] +external_theme = false +config_dir = '~/.config/sway/' +config_file = 'config' +supported_oses = ['Linux'] +#refresh_cmd = 'swaymsg reload' + +[app.waybar] +external_theme = false +config_dir = '~/.config/waybar/' +config_file = 'style.css' +supported_oses = ['Linux'] +refresh_cmd = 'swaymsg reload' diff --git a/autoconf/gen_theme.py b/autoconf/gen_theme.py new file mode 100644 index 0000000..dac99e0 --- /dev/null +++ b/autoconf/gen_theme.py @@ -0,0 +1,108 @@ +import argparse +import inspect +import json +import tomllib as toml +from pathlib import Path + +def get_running_path(): + calling_module = inspect.getmodule(inspect.stack()[-1][0]) + return Path(calling_module.__file__).parent + + +parser = argparse.ArgumentParser( + description='Generate theme files for various applications. Uses a template (in TOML ' \ + + 'format) to map application-specific config keywords to colors (in JSON ' \ + + 'format).' +) +parser.add_argument( + '-a', '--app', + required=True, + help='Application target for theme. Supported: ["kitty"]' +) +parser.add_argument( + '-p', '--palette', + required=True, + help='Palette to use for template mappings. Uses local "theme//colors.json".' +) +parser.add_argument( + '-t', '--template', + default=None, + help='Path to TOML template file. If omitted, app\'s default template path is used.' \ + + 'If a directory is provided, all TOML files in the folder will be used.' +) +parser.add_argument( + '-o', '--output', + default=None, + help='Output file path for theme. If omitted, app\'s default theme output path is used.' +) +args = parser.parse_args() + +# separation sequences to use base on app +app_sep_map = { + 'kitty': ' ', +} + +def generate_theme_files(): + basepath = get_running_path() + + # set arg conditional variables + palette_path = Path(basepath, 'themes', args.palette) + colors_path = Path(palette_path, 'colors.json') + theme_app = args.app + + template_path = None + output_path = None + + if args.template is None: + template_path = Path(palette_path, 'apps', theme_app, 'templates') + else: + template_path = Path(args.template).resolve() + + if args.output is None: + output_path = Path(palette_path, 'apps', theme_app, 'generated') + else: + output_path = Path(args.output).resolve() + + # check paths + if not colors_path.exists(): + print(f'Resolved colors path [{colors_path}] doesn\'t exist, exiting') + return + + if not template_path.exists(): + print(f'Template path [{template_path}] doesn\'t exist, exiting') + return + + if not output_path.exists() or not output_path.is_dir(): + print(f'Output path [{output_path}] doesn\'t exist or not a directory, exiting') + return + + print(f'Using palette colors [{colors_path}]') + print(f'-> with templates in [{template_path}]') + print(f'-> to output path [{output_path}]\n') + + # load external files (JSON, TOML) + colors_json = json.load(colors_path.open()) + + # get all matching TOML files + template_list = [template_path] + if template_path.is_dir(): + template_list = template_path.rglob('*.toml') + + for template_path in template_list: + template_toml = toml.load(template_path.open('rb')) + + # lookup app-specific config separator + config_sep = app_sep_map.get(theme_app, ' ') + output_lines = [] + for config_key, color_key in template_toml.items(): + color_value = colors_json + for _key in color_key.split('.'): + color_value = color_value.get(_key, {}) + output_lines.append(f'{config_key}{config_sep}{color_value}') + + output_file = Path(output_path, template_path.stem).with_suffix('.conf') + output_file.write_text('\n'.join(output_lines)) + print(f'[{len(output_lines)}] lines written to [{output_file}] for app [{theme_app}]') + +if __name__ == '__main__': + generate_theme_files() diff --git a/autoconf/set_theme.py b/autoconf/set_theme.py new file mode 100644 index 0000000..09b1129 --- /dev/null +++ b/autoconf/set_theme.py @@ -0,0 +1,145 @@ +import argparse +import inspect +import subprocess +import json +import os +import tomllib as toml +from pathlib import Path + +from colorama import Fore + + +parser = argparse.ArgumentParser( + description='Generate theme files for various applications. Uses a template (in TOML ' \ + + 'format) to map application-specific config keywords to colors (in JSON ' \ + + 'format).' +) +parser.add_argument( + '-p', '--palette', + required=True, + help='Palette name, must match a folder in themes/' +) +parser.add_argument( + '-s', '--scheme', + required=True, + help='Preferred lightness scheme, either "light" or "dark".' +) +parser.add_argument( + '-a', '--app', + required=True, + help='Application target for theme. App must be present in the registry. ' \ + + 'Use "*" to apply to all registered apps' +) +args = parser.parse_args() + + +def get_running_path(): + calling_module = inspect.getmodule(inspect.stack()[-1][0]) + return Path(calling_module.__file__).parent + +def os_scheme_settings(scheme): + ''' + Groups of settings/commands to invoke globally based on the provided `scheme`. This + may control things like default app light/dark behavior, for instance. + ''' + os_cmd_groups = { + 'Linux': [ + "gsettings set org.gnome.desktop.interface color-scheme 'prefer-{scheme}'", + ], + 'Darwin': [], + } + + if scheme not in ['light', 'dark']: return + osname = os.uname().sysname + cmd_list = os_cmd_groups.get(osname, []) + + for cmd in cmd_list: + subprocess.check_call(cmd.format(scheme=scheme).split()) + +def update_theme_settings(): + osname = os.uname().sysname + basepath = get_running_path() + app_registry = toml.load(Path(basepath, 'app_registry.toml').open('rb')) + app_registry = app_registry.get('app', {}) + + if args.app not in app_registry and args.app != '*': + print(f'App {args.app} not registered, exiting') + return + + app_list = [] + if args.app == '*': + app_list = list(app_registry.items()) + else: + app_list = [(args.app, app_registry[args.app])] + + links_succ = {} + links_fail = {} + for app_name, app_settings in app_list: + config_dir = Path(app_settings['config_dir']).expanduser() + config_file = app_settings['config_file'] + config_path = Path(config_dir, config_file) + + if osname not in app_settings['supported_oses']: + print(f'OS [{osname}] not support for app [{app_name}]') + continue + + if app_settings['external_theme']: + # symlink from "current-theme.conf" in app's config-dir ... + from_conf_path = Path(config_dir, 'current-theme.conf') + + # ... to appropriate generated theme path here in local-config + to_conf_path = Path( + basepath, + f'themes/{args.palette}/apps/{app_name}/generated/{args.scheme}.conf' + ) + else: + # symlink from the canonical config file ... + from_conf_path = config_path + + # ... to appropriate theme variant + to_conf_path = Path( + config_dir, + f'{app_name}-{args.palette}-{args.scheme}{config_path.suffix}' + ) + + if not to_conf_path.exists(): + print( + f'Expected symlink target [{to_conf_path}] doesn\'t exist, skipping' + ) + links_fail[app_name] = (from_conf_path.name, to_conf_path.name) + continue + + # if config file being symlinked exists & isn't already a symlink (i.e., + # previously set by this script), throw an error. + if from_conf_path.exists() and not from_conf_path.is_symlink(): + print( + f'Symlink origin [{from_conf_path}] exists and isn\'t a symlink; please ' \ + + 'first manually remove this file so this script can set the symlink.' + ) + links_fail[app_name] = (from_conf_path.name, to_conf_path.name) + continue + else: + # if path doesn't exist, or exists and is symlink, remove the symlink in + # preparation for the new symlink setting + from_conf_path.unlink(missing_ok=True) + + print(f'Linking [{from_conf_path}] -> [{to_conf_path}]') + + # run color scheme live-reload for app, if available + # TODO: store the status of this cmd & print with the messages + if 'refresh_cmd' in app_settings: + subprocess.check_call(app_settings['refresh_cmd'], shell=True) + + from_conf_path.symlink_to(to_conf_path) + links_succ[app_name] = (from_conf_path.name, to_conf_path.name) + + for app, (from_p, to_p) in links_succ.items(): + print(Fore.GREEN + f'> {app} :: {from_p} -> {to_p}') + + for app, (from_p, to_p) in links_fail.items(): + print(Fore.RED + f'> {app} :: {from_p} -> {to_p}') + + +if __name__ == '__main__': + os_scheme_settings(args.scheme) + update_theme_settings() diff --git a/autoconf/themes/tone4/apps/kitty/generated/dark.conf b/autoconf/themes/tone4/apps/kitty/generated/dark.conf new file mode 100644 index 0000000..2f3772f --- /dev/null +++ b/autoconf/themes/tone4/apps/kitty/generated/dark.conf @@ -0,0 +1,21 @@ +background #1b1b1b +foreground #c6c6c6 +selection_background #303030 +selection_foreground #ababab +cursor #d4d4d4 +color0 #262626 +color8 #262626 +color1 #ed625d +color9 #ed625d +color2 #34a543 +color10 #34a543 +color3 #a68f03 +color11 #a68f03 +color4 #618eff +color12 #618eff +color5 #ed625d +color13 #ed625d +color6 #618eff +color14 #618eff +color7 #d4d4d4 +color15 #d4d4d4 \ No newline at end of file diff --git a/autoconf/themes/tone4/apps/kitty/generated/light.conf b/autoconf/themes/tone4/apps/kitty/generated/light.conf new file mode 100644 index 0000000..972d9b9 --- /dev/null +++ b/autoconf/themes/tone4/apps/kitty/generated/light.conf @@ -0,0 +1,21 @@ +background #f1f1f1 +foreground #262626 +selection_background #ababab +selection_foreground #303030 +cursor #262626 +color0 #1b1b1b +color8 #1b1b1b +color1 #c25244 +color9 #c25244 +color2 #298835 +color10 #298835 +color3 #897600 +color11 #897600 +color4 #4e75d4 +color12 #4e75d4 +color5 #c25244 +color13 #c25244 +color6 #4e75d4 +color14 #4e75d4 +color7 #d4d4d4 +color15 #d4d4d4 \ No newline at end of file diff --git a/autoconf/themes/tone4/apps/kitty/templates/dark.toml b/autoconf/themes/tone4/apps/kitty/templates/dark.toml new file mode 100644 index 0000000..9b8900d --- /dev/null +++ b/autoconf/themes/tone4/apps/kitty/templates/dark.toml @@ -0,0 +1,40 @@ +# base settings +background = 'black.bg+1' +foreground = 'black.fg+3' + +selection_background = 'black.bg+3' +selection_foreground = 'black.m+4' + +cursor = 'black.fg+2' + +# black +color0 = 'black.bg+2' +color8 = 'black.bg+2' + +# red +color1 = 'red.m+2' +color9 = 'red.m+2' + +# green +color2 = 'green.m+2' +color10 = 'green.m+2' + +# yellow +color3 = 'yellow.m+2' +color11 = 'yellow.m+2' + +# blue +color4 = 'blue.m+2' +color12 = 'blue.m+2' + +# purple (red) +color5 = 'red.m+2' +color13 = 'red.m+2' + +# cyan (blue) +color6 = 'blue.m+2' +color14 = 'blue.m+2' + +## white +color7 = 'black.fg+2' +color15 = 'black.fg+2' diff --git a/autoconf/themes/tone4/apps/kitty/templates/light.toml b/autoconf/themes/tone4/apps/kitty/templates/light.toml new file mode 100644 index 0000000..9e862d9 --- /dev/null +++ b/autoconf/themes/tone4/apps/kitty/templates/light.toml @@ -0,0 +1,40 @@ +# base settings +background = 'black.fg+1' +foreground = 'black.bg+2' + +selection_background = 'black.m+4' +selection_foreground = 'black.bg+3' + +cursor = 'black.bg+2' + +# black +color0 = 'black.bg+1' +color8 = 'black.bg+1' + +# red +color1 = 'red.m+0' +color9 = 'red.m+0' + +# green +color2 = 'green.m+0' +color10 = 'green.m+0' + +# yellow +color3 = 'yellow.m+0' +color11 = 'yellow.m+0' + +# blue +color4 = 'blue.m+0' +color12 = 'blue.m+0' + +# purple (red) +color5 = 'red.m+0' +color13 = 'red.m+0' + +# cyan (blue) +color6 = 'blue.m+0' +color14 = 'blue.m+0' + +## white +color7 = 'black.fg+2' +color15 = 'black.fg+2' diff --git a/autoconf/themes/tone4/colors.json b/autoconf/themes/tone4/colors.json new file mode 100644 index 0000000..27cb9b3 --- /dev/null +++ b/autoconf/themes/tone4/colors.json @@ -0,0 +1,107 @@ +{ + "red": { + "bg+0": "#1c0d0a", + "bg+1": "#2d1412", + "bg+2": "#401a17", + "bg+3": "#531f1d", + "bg+4": "#652624", + "m-4": "#782d2b", + "m-3": "#8b3633", + "m-2": "#9d3e3b", + "m-1": "#b14643", + "m+0": "#c25244", + "m+1": "#d95854", + "m+2": "#ed625d", + "m+3": "#f27870", + "m+4": "#f68c83", + "fg+4": "#faa097", + "fg+3": "#fdb3ab", + "fg+2": "#fec6c0", + "fg+1": "#ffdad3", + "fg+0": "#ffede9" + }, + "yellow": { + "bg+0": "#151100", + "bg+1": "#211b00", + "bg+2": "#2d2500", + "bg+3": "#393000", + "bg+4": "#453b00", + "m-4": "#524600", + "m-3": "#5f5100", + "m-2": "#6d5d00", + "m-1": "#7a6900", + "m+0": "#897600", + "m+1": "#978200", + "m+2": "#a68f03", + "m+3": "#b29c34", + "m+4": "#bfaa53", + "fg+4": "#cbb770", + "fg+3": "#d6c58c", + "fg+2": "#e1d3a9", + "fg+1": "#ebe2c5", + "fg+0": "#f5f0e2" + }, + "green": { + "bg+0": "#081406", + "bg+1": "#0e1f0c", + "bg+2": "#0f2c10", + "bg+3": "#103814", + "bg+4": "#114518", + "m-4": "#15521d", + "m-3": "#1a5f23", + "m-2": "#1e6c29", + "m-1": "#247a2f", + "m+0": "#298835", + "m+1": "#2e973b", + "m+2": "#34a543", + "m+3": "#56b15a", + "m+4": "#71bc72", + "fg+4": "#8ac789", + "fg+3": "#a2d3a0", + "fg+2": "#badeb8", + "fg+1": "#d1e9cf", + "fg+0": "#e8f4e7" + }, + "blue": { + "bg+0": "#0f101b", + "bg+1": "#151b2f", + "bg+2": "#1a2544", + "bg+3": "#202f59", + "bg+4": "#263a6e", + "m-4": "#2d4582", + "m-3": "#355196", + "m-2": "#3d5daa", + "m-1": "#4669bf", + "m+0": "#4e75d4", + "m+1": "#5781ea", + "m+2": "#618eff", + "m+3": "#7b9bff", + "m+4": "#91a9ff", + "fg+4": "#a6b7ff", + "fg+3": "#b9c5ff", + "fg+2": "#cbd3ff", + "fg+1": "#dde1ff", + "fg+0": "#eef0fe" + }, + "black": { + "bg+0": "#111111", + "bg+1": "#1b1b1b", + "bg+2": "#262626", + "bg+3": "#303030", + "bg+4": "#3b3b3b", + "m-4": "#474747", + "m-3": "#525252", + "m-2": "#5e5e5e", + "m-1": "#6a6a6a", + "m+0": "#777777", + "m+1": "#848484", + "m+2": "#919191", + "m+3": "#9e9e9e", + "m+4": "#ababab", + "fg+4": "#b9b9b9", + "fg+3": "#c6c6c6", + "fg+2": "#d4d4d4", + "fg+1": "#e2e2e2", + "fg+0": "#f1f1f1" + } +} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..600e05f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +sphinx +furo +myst-parser