home | blog | art | git gpg | email | rss

morph

A Linux rice color switching tool
git clone git://pollux.codes/git/morph.git
Log | Files | Refs
commit 21080d07492028ac39bfbad8688239a5b23e0c71
Author: Pollux <pollux@pollux.codes>
Date:   Sun, 13 Apr 2025 22:07:09 -0500

feat: initial commit

Signed-off-by: Pollux <pollux@pollux.codes>

Diffstat:
A.gitignore | 2++
Apyproject.toml | 16++++++++++++++++
Asrc/morph.py | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atheme.toml | 8++++++++
4 files changed, 143 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,2 @@ +src/morph.egg-info +src/__pycache__ diff --git a/pyproject.toml b/pyproject.toml @@ -0,0 +1,16 @@ +[build-system] +requires = ["setuptools", "setuptools-scm"] +build-backend = "setuptools.build_meta" + +[project] +name = "morph" +version = "0.0" +authors = [ + { name = "Pollux", email = "pollux@pollux.codes" } +] +description = "" +readme = "README.md" +requires-python = ">=3.13" + +[project.scripts] +morph = "morph:main" diff --git a/src/morph.py b/src/morph.py @@ -0,0 +1,117 @@ +import argparse +import tomllib +import os +import subprocess +import glob +import re + +template_regex = re.compile('{{([^}:]*)(?::([^}]*))?}}') + +def get_destination_dir(cmdline): + if cmdline != None: + return cmdline + home=os.getenv('HOME') + return f'{home}/.cache/morph' + +def get_templates_dir(cmdline): + if cmdline != None: + return cmdline + + xdg_config_home=os.getenv('XDG_CONFIG_HOME') + home=os.getenv('HOME') + + if xdg_config_home != None: + return f'{xdg_config_home}/morph/templates' + return f'{home}/.config/morph/templates' + +def get_config_file(cmdline): + if cmdline != None: + return cmdline + + xdg_config_home=os.getenv('XDG_CONFIG_HOME') + home=os.getenv('HOME') + + if xdg_config_home != None: + return f'{xdg_config_home}/morph/config.toml' + return f'{home}/.config/morph/config.toml' + +def replace_colors(theme): + def tmp(match): + color = match.group(1) + format = match.group(2) + if format == None: + format = 'hex_rgba' + + hex = theme[color] + r = int(hex[:2],16) + g = int(hex[2:4],16) + b = int(hex[4:6],16) + a = int(hex[6:8],16) + + match format: + case 'hex_rgba': + return hex + case 'hex_rgb': + return hex[:6] + case 'int_rgba': + return f'{r}, {g}, {b}, {a}' + case 'int_rgb': + return f'{r}, {g}, {b}' + case 'float_rgba': + return f'{r/255}, {g/255}, {b/255}, {a/255}' + case 'float_rgb': + return f'{r/255}, {g/255}, {b/255}' + return tmp + +def main(): + + parser = argparse.ArgumentParser( + prog='morph', + description='Linux color ricer') + + parser.add_argument('theme') + parser.add_argument('-c', '--config') + parser.add_argument('-t', '--templates') + parser.add_argument('-d', '--destination') + parser.add_argument('-v', '--verbose', action='store_true') + + args = parser.parse_args() + + config_file = get_config_file(args.config) + templates_dir = get_templates_dir(args.templates) + destination_dir = get_destination_dir(args.destination) + + with open(config_file, 'rb') as f: + themes = tomllib.load(f) + + if args.verbose: + print(f'Config File: {config_file}') + print(f'Templates: {templates_dir}') + print(f'Destination: {destination_dir}') + print(f'Applying theme: {args.theme}') + + theme = themes[args.theme] + + if 'pre-exec' in theme: + subprocess.run(theme['pre-exec'], shell=True) + + files = glob.glob('**', root_dir=templates_dir, recursive=True) + + for file in files: + if os.path.isdir(f'{templates_dir}/{file}'): + os.makedirs(f'{destination_dir}/{file}', exist_ok=True) + continue + + src_file = f'{templates_dir}/{file}' + dest_file = f'{destination_dir}/{file}' + + with open(src_file, 'r') as f: + src_string = f.read() + + out_string = re.sub(template_regex, replace_colors(theme), src_string) + + with open(dest_file, 'w') as f: + f.write(out_string) + + if 'post-exec' in theme: + subprocess.run(theme['post-exec'], shell=True) diff --git a/theme.toml b/theme.toml @@ -0,0 +1,8 @@ +[general] +pre-exec="test" +post-exec="test" + +[colors] +a="ffffff" +b="000000" +c="cccccc"