diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..3550a30f --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b9f705e4..d541b90d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,9 +4,11 @@ on: push: tags: - "v*" - jobs: release: + strategy: + matrix: + flavor: [mocha, macchiato, latte, frappe] runs-on: ubuntu-latest steps: - name: Checkout @@ -15,14 +17,14 @@ jobs: submodules: true - uses: actions/setup-python@v5 with: - python-version: '3.11' - cache: 'pip' + python-version: "3.11" + cache: "pip" - name: Install dependencies run: pip install -r requirements.txt - name: Install colloid specific dependencies run: sudo apt update && sudo apt install -y sassc inkscape optipng - name: Generate themes - run: python ./install.py all -a all --zip -d $PWD/releases --recreate-asset + run: python ./build.py ${{ matrix.flavor }} -a all --zip -d $PWD/releases - name: Add zips to release uses: softprops/action-gh-release@v2 with: diff --git a/.gitignore b/.gitignore index 18889102..cb11597c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ venv/ bin/ lib*/ *.cfg +.direnv +build/ # Releases folder releases diff --git a/build.py b/build.py new file mode 100755 index 00000000..a0e70085 --- /dev/null +++ b/build.py @@ -0,0 +1,681 @@ +#! /usr/bin/env python3 +import os, re, shutil, subprocess, argparse, glob, logging, zipfile + +from dataclasses import dataclass +from typing import Literal, List + +from catppuccin import PALETTE +from catppuccin.models import Flavor, Color + +THIS_DIR = os.path.dirname(os.path.realpath(__file__)) +SRC_DIR = f"{THIS_DIR}/colloid/src" +SASSC_OPT = ["-M", "-t", "expanded"] + +logger = logging.getLogger("catppuccin-gtk") +logger.setLevel(logging.DEBUG) +ch = logging.StreamHandler() +formatter = logging.Formatter("[%(name)s] [%(levelname)s] - %(message)s") +ch.setFormatter(formatter) +logger.addHandler(ch) + + +@dataclass +class Tweaks: + tweaks: List[str] + + def has(self, tweak: str) -> bool: + return tweak in self.tweaks + + def id(self) -> str: + return ",".join(self.tweaks) + + +@dataclass +class BuildContext: + build_root: str + output_format: Literal["zip"] | Literal["dir"] + theme_name: str + flavor: Flavor + accent: Color + size: Literal["standard"] | Literal["compact"] + tweaks: Tweaks + + def output_dir(self) -> str: + return f"{self.build_root}/{self.build_id()}" + + def build_id(self) -> str: + return f"{self.theme_name}-{self.flavor.identifier}-{self.accent.identifier}-{self.size}+{self.tweaks.id() or 'default'}" + + +def build(ctx: BuildContext): + dark_suffix = "" + light_suffix = "" + window_suffix = "" + scheme_suffix = "-Catppuccin" + + if ctx.tweaks.has("normal"): + window_suffix = "-Normal" + + if ctx.flavor == "latte": + light_suffix = "-Light" + suffix = "-Light" + + if ctx.flavor != "": + dark_suffix = "-Dark" + suffix = "-Dark" + + output_dir = ctx.output_dir() + # [[ -d "${THEME_DIR}" ]] && rm -rf "${THEME_DIR}" + logger.info(f"Building into '{output_dir}'...") + + apply_tweaks(ctx) + + os.makedirs(output_dir, exist_ok=True) + with open(f"{output_dir}/index.theme", "w") as file: + file.write("[Desktop Entry]\n") + file.write("Type=X-GNOME-Metatheme\n") + file.write(f"Name={ctx.build_id()}\n") + file.write("Comment=An Flat Gtk+ theme based on Elegant Design\n") + file.write("Encoding=UTF-8\n") + file.write("\n") + file.write("[X-GNOME-Metatheme]\n") + file.write(f"GtkTheme={ctx.build_id()}\n") + file.write(f"MetacityTheme={ctx.build_id()}\n") + file.write(f"IconTheme=Tela-circle{dark_suffix}\n") + file.write(f"CursorTheme={ctx.flavor.name}-cursors\n") + file.write("ButtonLayout=close,minimize,maximize:menu\n") + + os.makedirs(f"{output_dir}/gnome-shell", exist_ok=True) + shutil.copyfile( + f"{SRC_DIR}/main/gnome-shell/pad-osd.css", + f"{output_dir}/gnome-shell/pad-osd.css", + ) + subprocess.check_call( + [ + "sassc", + *SASSC_OPT, + f"{SRC_DIR}/main/gnome-shell/gnome-shell{suffix}.scss", + f"{output_dir}/gnome-shell/gnome-shell.css", + ] + ) + + os.makedirs(f"{output_dir}/gtk-3.0", exist_ok=True) + subprocess.check_call( + [ + "sassc", + *SASSC_OPT, + f"{SRC_DIR}/main/gtk-3.0/gtk{suffix}.scss", + f"{output_dir}/gtk-3.0/gtk.css", + ] + ) + subprocess.check_call( + [ + "sassc", + *SASSC_OPT, + # NOTE: This uses 'Dark' for the source, but 'dark' for the destination. This is intentional. Do !!NOT!! change it without consultation + f"{SRC_DIR}/main/gtk-3.0/gtk-Dark.scss", + f"{output_dir}/gtk-3.0/gtk-dark.css", + ] + ) + + os.makedirs(f"{output_dir}/gtk-4.0", exist_ok=True) + subprocess.check_call( + [ + "sassc", + *SASSC_OPT, + f"{SRC_DIR}/main/gtk-4.0/gtk{suffix}.scss", + f"{output_dir}/gtk-4.0/gtk.css", + ] + ) + subprocess.check_call( + [ + "sassc", + *SASSC_OPT, + # NOTE: This uses 'Dark' for the source, but 'dark' for the destination. This is intentional. Do !!NOT!! change it without consultation + f"{SRC_DIR}/main/gtk-4.0/gtk-Dark.scss", + f"{output_dir}/gtk-4.0/gtk-dark.css", + ] + ) + + os.makedirs(f"{output_dir}/cinnamon", exist_ok=True) + subprocess.check_call( + [ + "sassc", + *SASSC_OPT, + f"{SRC_DIR}/main/cinnamon/cinnamon{suffix}.scss", + f"{output_dir}/cinnamon/cinnamon.css", + ] + ) + + os.makedirs(f"{output_dir}/metacity-1", exist_ok=True) + shutil.copyfile( + f"{SRC_DIR}/main/metacity-1/metacity-theme-3{window_suffix}.xml", + f"{output_dir}/metacity-1/metacity-theme-3.xml", + ) + # FIXME: Symlinks aren't working as intended + # FIXME: Do we need them? + # os.symlink( + # f"{output_dir}/metacity-1/metacity-theme-3.xml", + # f"{output_dir}/metacity-1/metacity-theme-2.xml", + # ) + # os.symlink( + # f"{output_dir}/metacity-1/metacity-theme-3.xml", + # f"{output_dir}/metacity-1/metacity-theme-1.xml", + # ) + + os.makedirs(f"{output_dir}/xfwm4", exist_ok=True) + shutil.copyfile( + f"{SRC_DIR}/main/xfwm4/themerc{light_suffix}", + f"{output_dir}/xfwm4/themerc", + ) + + os.makedirs(f"{output_dir}-hdpi/xfwm4", exist_ok=True) + shutil.copyfile( + f"{SRC_DIR}/main/xfwm4/themerc{light_suffix}", + f"{output_dir}-hdpi/xfwm4/themerc", + ) + subst_text(f"{output_dir}-hdpi/xfwm4/themerc", "button_offset=6", "button_offset=9") + + os.makedirs(f"{output_dir}-xhdpi/xfwm4", exist_ok=True) + shutil.copyfile( + f"{SRC_DIR}/main/xfwm4/themerc{light_suffix or ''}", + f"{output_dir}-xhdpi/xfwm4/themerc", + ) + subst_text( + f"{output_dir}-xhdpi/xfwm4/themerc", "button_offset=6", "button_offset=12" + ) + + if not ctx.flavor.dark: + shutil.copytree( + f"{SRC_DIR}/main/plank/theme-Light{scheme_suffix}/", f"{output_dir}/plank" + ) + else: + shutil.copytree( + f"{SRC_DIR}/main/plank/theme-Dark{scheme_suffix}/", f"{output_dir}/plank" + ) + + +def tweaks_temp(): + shutil.copyfile(f"{SRC_DIR}/sass/_tweaks.scss", f"{SRC_DIR}/sass/_tweaks-temp.scss") + + +def subst_text(path, _from, to): + with open(path, "r+") as f: + content = f.read() + f.seek(0) + f.truncate() + f.write(re.sub(_from, to, content)) + + +GS_VERSION = "46-0" + + +def gnome_shell_version(): + shutil.copyfile( + f"{SRC_DIR}/sass/gnome-shell/_common.scss", + f"{SRC_DIR}/sass/gnome-shell/_common-temp.scss", + ) + subst_text( + f"{SRC_DIR}/sass/gnome-shell/_common-temp.scss", + "@import 'widgets-40-0';", + f"@import 'widgets-{GS_VERSION}';", + ) + + if GS_VERSION == "3-28": + subst_text( + f"{SRC_DIR}/sass/gnome-shell/_common-temp.scss", + "@import 'extensions-40-0';", + f"@import 'extensions-{GS_VERSION}';", + ) + + +# Accent translation +ctp_to_colloid = { + "rosewater": "pink", + "flamingo": "pink", + "pink": "pink", + "mauve": "purple", + "red": "red", + "maroon": "red", + "peach": "orange", + "yellow": "yellow", + "green": "green", + "teal": "teal", + "sky": "teal", + "sapphire": "default", + "blue": "default", + "lavender": "default", +} + + +def translate_accent(ctp_accent: Color): + return ctp_to_colloid[ctp_accent.identifier] + + +def write_tweak(key, default, value): + subst_text( + f"{SRC_DIR}/sass/_tweaks-temp.scss", f"\\${key}: {default}", f"${key}: {value}" + ) + + +def apply_tweaks(ctx: BuildContext): + write_tweak("theme", "'default'", translate_accent(ctx.accent)) + + if ctx.size == "compact": + write_tweak("compact", "'false'", "'true'") + + subst_text( + f"{SRC_DIR}/sass/_tweaks-temp.scss", + "@import 'color-palette-default';", + f"@import 'color-palette-catppuccin-{ctx.flavor.identifier}';", + ) + write_tweak("colorscheme", "'default'", "'catppuccin'") + + if ctx.tweaks.has("black"): + write_tweak("blackness", "'false'", "'true'") + + if ctx.tweaks.has("rimless"): + write_tweak("rimless", "'false'", "'true'") + + if ctx.tweaks.has("normal"): + write_tweak("window_button", "'mac'", "'normal'") + + if ctx.tweaks.has("float"): + write_tweak("float", "'false'", "'true'") + + +def make_assets(ctx: BuildContext): + color_suffix = "" + if not ctx.flavor.dark: + color_suffix = "-Light" + else: + color_suffix = "-Dark" + + dark_suffix = "" + if ctx.flavor.dark: + dark_suffix = "-Dark" + + light_suffix = "" + if not ctx.flavor.dark: + light_suffix = "-Light" + + window_suffix = "" + if ctx.tweaks.has("normal"): + window_suffix = "-Normal" + + output_dir = ctx.output_dir() + + os.makedirs(f"{output_dir}/cinnamon/assets", exist_ok=True) + for file in glob.glob(f"{SRC_DIR}/assets/cinnamon/theme/*.svg"): + shutil.copy(file, f"{output_dir}/cinnamon/assets") + shutil.copy( + f"{SRC_DIR}/assets/cinnamon/thumbnail{color_suffix}.svg", + f"{output_dir}/cinnamon/thumbnail.png", + ) + + os.makedirs(f"{output_dir}/gnome-shell/assets", exist_ok=True) + for file in glob.glob(f"{SRC_DIR}/assets/gnome-shell/theme/*.svg"): + shutil.copy(file, f"{output_dir}/gnome-shell/assets") + + shutil.copytree( + f"{SRC_DIR}/assets/gtk/assets", + f"{output_dir}/gtk-3.0/assets", + dirs_exist_ok=True, + ) + shutil.copytree( + f"{SRC_DIR}/assets/gtk/assets", + f"{output_dir}/gtk-4.0/assets", + dirs_exist_ok=True, + ) + shutil.copyfile( + f"{SRC_DIR}/assets/gtk/thumbnail{dark_suffix}.svg", + f"{output_dir}/gtk-3.0/thumbnail.png", + ) + shutil.copyfile( + f"{SRC_DIR}/assets/gtk/thumbnail{dark_suffix}.svg", + f"{output_dir}/gtk-4.0/thumbnail.png", + ) + + theme_color = ctx.accent.hex + + palette = ctx.flavor.colors + background = palette.base.hex + background_alt = palette.mantle.hex + titlebar = palette.overlay0.hex + + for file in glob.glob(f"{output_dir}/cinnamon/assets/*.svg"): + subst_text(file, "#5b9bf8", theme_color) + subst_text(file, "#3c84f7", theme_color) + + for file in glob.glob(f"{output_dir}/gnome-shell/assets/*.svg"): + subst_text(file, "#5b9bf8", theme_color) + subst_text(file, "#3c84f7", theme_color) + + for file in glob.glob(f"{output_dir}/gtk-3.0/assets/*.svg"): + subst_text(file, "#5b9bf8", theme_color) + subst_text(file, "#3c84f7", theme_color) + subst_text(file, "#ffffff", background) + subst_text(file, "#2c2c2c", background) + subst_text(file, "#3c3c3c", background_alt) + + for file in glob.glob(f"{output_dir}/gtk-4.0/assets/*.svg"): + subst_text(file, "#5b9bf8", theme_color) + subst_text(file, "#3c84f7", theme_color) + subst_text(file, "#ffffff", background) + subst_text(file, "#2c2c2c", background) + subst_text(file, "#3c3c3c", background_alt) + + if ctx.flavor.dark: + subst_text(f"{output_dir}/cinnamon/thumbnail.png", "#2c2c2c", background) + subst_text(f"{output_dir}/cinnamon/thumbnail.png", "#5b9bf8", theme_color) + + subst_text(f"{output_dir}/gtk-3.0/thumbnail.png", "#2c2c2c", background) + subst_text(f"{output_dir}/gtk-4.0/thumbnail.png", "#2c2c2c", background) + + subst_text(f"{output_dir}/gtk-3.0/thumbnail.png", "#5b9bf8", theme_color) + subst_text(f"{output_dir}/gtk-4.0/thumbnail.png", "#5b9bf8", theme_color) + else: + subst_text(f"{output_dir}/cinnamon/thumbnail.png", "#ffffff", background) + subst_text(f"{output_dir}/cinnamon/thumbnail.png", "#f2f2f2", titlebar) + subst_text(f"{output_dir}/cinnamon/thumbnail.png", "#3c84f7", theme_color) + + subst_text(f"{output_dir}/gtk-3.0/thumbnail.png", "#f2f2f2", titlebar) + subst_text(f"{output_dir}/gtk-3.0/thumbnail.png", "#3c84f7", theme_color) + + subst_text(f"{output_dir}/gtk-4.0/thumbnail.png", "#f2f2f2", titlebar) + subst_text(f"{output_dir}/gtk-4.0/thumbnail.png", "#3c84f7", theme_color) + + for file in glob.glob(f"{SRC_DIR}/assets/cinnamon/common-assets/*.svg"): + shutil.copy(file, f"{output_dir}/cinnamon/assets") + + for file in glob.glob(f"{SRC_DIR}/assets/cinnamon/assets-{dark_suffix}/*.svg"): + shutil.copy(file, f"{output_dir}/cinnamon/assets") + + for file in glob.glob(f"{SRC_DIR}/assets/gnome-shell/common-assets/*.svg"): + shutil.copy(file, f"{output_dir}/gnome-shell/assets") + + for file in glob.glob(f"{SRC_DIR}/assets/gnome-shell/assets-{dark_suffix}/*.svg"): + shutil.copy(file, f"{output_dir}/gnome-shell/assets") + + for file in glob.glob(f"{SRC_DIR}/assets/gtk/symbolics/*.svg"): + shutil.copy(file, f"{output_dir}/gtk-3.0/assets") + shutil.copy(file, f"{output_dir}/gtk-4.0/assets") + + for file in glob.glob(f"{SRC_DIR}/assets/metacity-1/assets-{window_suffix}/*.svg"): + shutil.copy(file, f"{output_dir}/metacity-1/assets") + shutil.copy( + f"{SRC_DIR}/assets/metacity-1/thumbnail{dark_suffix}.png", + f"{output_dir}/metacity-1/thumbnail.png", + ) + + # TODO: Make our own assets for this and patch them in with the patch system, then code it to be + # {src_dir}/assets/xfwm4/assets{light_suffix}-Catppuccin/ + # where assets-Light-Catppuccin will have latte + # nad assets-Catppuccin will have mocha or something + for file in glob.glob(f"{SRC_DIR}/assets/xfwm4/assets{light_suffix}/*.png"): + shutil.copy(file, f"{output_dir}/xfwm4") + + for file in glob.glob(f"{SRC_DIR}/assets/xfwm4/assets{light_suffix}-hdpi/*.png"): + shutil.copy(file, f"{output_dir}-hdpi/xfwm4") + + for file in glob.glob(f"{SRC_DIR}/assets/xfwm4/assets{light_suffix}-xhdpi/*.png"): + shutil.copy(file, f"{output_dir}-xhdpi/xfwm4") + + +def zip_dir(path, zip_file): + # Ref: https://stackoverflow.com/questions/46229764/python-zip-multiple-directories-into-one-zip-file + for root, _, files in os.walk(path): + for file in files: + zip_file.write( + os.path.join(root, file), + os.path.relpath(os.path.join(root, file), os.path.join(path, "..")), + ) + + +def zip_artifacts(dir_list, zip_name, remove=True): + with zipfile.ZipFile(zip_name, "w", zipfile.ZIP_DEFLATED) as zipf: + for dir in dir_list: + zip_dir(dir, zipf) + + if remove: + for dir in dir_list: + shutil.rmtree(dir) + + +def build_theme(ctx: BuildContext): + build_info = f"""Build info: + build_root: {ctx.build_root} + theme_name: {ctx.theme_name} + flavor: {ctx.flavor.identifier} + accent: {ctx.accent.identifier} + size: {ctx.size} + tweaks: {ctx.tweaks}""" + logger.info(build_info) + build(ctx) + logger.info(f"Main build complete") + + logger.info("Bundling assets...") + make_assets(ctx) + logger.info("Asset bundling done") + + if ctx.output_format == "zip": + zip_artifacts( + [ + ctx.output_dir(), + f"{ctx.output_dir()}-hdpi", + f"{ctx.output_dir()}-xhdpi", + ], + f"{ctx.build_root}/{ctx.build_id()}.zip", + True, + ) + + """ + if (command -v xfce4-popup-whiskermenu &> /dev/null) && $(sed -i "s|.*menu-opacity=.*|menu-opacity=95|" "$HOME/.config/xfce4/panel/whiskermenu"*".rc" &> /dev/null); then + sed -i "s|.*menu-opacity=.*|menu-opacity=95|" "$HOME/.config/xfce4/panel/whiskermenu"*".rc" + fi + + if (pgrep xfce4-session &> /dev/null); then + xfce4-panel -r + fi + """ + + +def apply_colloid_patches(): + if os.path.isfile("colloid/.patched"): + logger.info( + 'Patches seem to be applied, remove "colloid/.patched" to force application (this may fail)' + ) + return + + logger.info("Applying patches...") + # Change into colloid + for patch in [ + "plank-dark.patch", + "plank-light.patch", + "sass-colors.patch", + "sass-palette-frappe.patch", + "sass-palette-mocha.patch", + "sass-palette-latte.patch", + "sass-palette-macchiato.patch", + ]: + path = f"./patches/colloid/{patch}" + logger.info(f"Applying patch '{patch}', located at '{path}'") + subprocess.check_call(["git", "apply", path, "--directory", f"colloid"]) + + with open("colloid/.patched", "w") as f: + f.write("true") + + logger.info("Patching finished.") + + +def parse_args(): + parser = argparse.ArgumentParser() + parser.add_argument( + "flavor", + type=str, + choices=["mocha", "frappe", "macchiato", "latte"], + help="Flavor of the theme to apply.", + ) + + parser.add_argument( + "--name", + "-n", + type=str, + default="catppuccin", + dest="name", + help="Name of the theme to apply.", + ) + + parser.add_argument( + "--dest", + "-d", + type=str, + required=True, + dest="dest", + help="Destination of the files.", + ) + + parser.add_argument( + "--accent", + "-a", + type=str, + default="mauve", + dest="accent", + choices=[ + "rosewater", + "flamingo", + "pink", + "mauve", + "red", + "maroon", + "peach", + "yellow", + "green", + "teal", + "sky", + "sapphire", + "blue", + "lavender", + "all" + ], + help="Accent of the theme.", + ) + + parser.add_argument( + "--size", + "-s", + type=str, + default="standard", + dest="size", + choices=["standard", "compact"], + help="Size variant of the theme.", + ) + + parser.add_argument( + "--tweaks", + type=str, + default=[], + nargs="+", + dest="tweaks", + choices=["black", "rimless", "normal", "float"], + help="Tweaks to apply to the build.", + ) + + parser.add_argument( + "--zip", + help="Whether to bundle the theme into a zip", + type=bool, + default=False, + action=argparse.BooleanOptionalAction, + ) + + parser.add_argument( + "--patch", + help="Whether to patch the colloid submodule", + type=bool, + default=True, + action=argparse.BooleanOptionalAction, + ) + + return parser.parse_args() + +def main(): + args = parse_args() + if args.patch: + apply_colloid_patches() + + palette = getattr(PALETTE, args.flavor) + accents=[ + "rosewater", + "flamingo", + "pink", + "mauve", + "red", + "maroon", + "peach", + "yellow", + "green", + "teal", + "sky", + "sapphire", + "blue", + "lavender", + ] + + if args.accent == 'all': + for accent in accents: + accent = getattr(palette.colors, accent) + + tweaks = Tweaks(tweaks=args.tweaks) + + if args.zip: + output_format = 'zip' + else: + output_format = 'dir' + + ctx = BuildContext( + build_root=args.dest, + theme_name=args.name, + flavor=palette, + accent=accent, + size=args.size, + tweaks=tweaks, + output_format=output_format + ) + + tweaks_temp() + gnome_shell_version() + build_theme(ctx) + logger.info("Done!") + else: + accent = getattr(palette.colors, args.accent) + tweaks = Tweaks(tweaks=args.tweaks) + + if args.zip: + output_format = 'zip' + else: + output_format = 'dir' + + ctx = BuildContext( + build_root=args.dest, + theme_name=args.name, + flavor=palette, + accent=accent, + size=args.size, + tweaks=tweaks, + output_format=output_format + ) + + logger.info("Building temp tweaks file") + tweaks_temp() + logger.info("Inserting gnome-shell imports") + gnome_shell_version() + logger.info("Building main theme") + build_theme(ctx) + logger.info("Done!") + + +try: + main() +except Exception as e: + logger.error("Something went wrong when building the theme:", exc_info=e) \ No newline at end of file diff --git a/install.py b/install.py index 4a5de802..7363514d 100644 --- a/install.py +++ b/install.py @@ -1,109 +1,147 @@ -""" -Main script to clone, recolor and install the theme. -Run this from the root of the repo. - -Usage: - python install.py [options] -""" -import argparse -import os -import subprocess - -from scripts.ctp_colors import get_all_accent, get_all_flavors -from scripts.create_theme import create_theme -from scripts.var import theme_name, work_dir - -parser = argparse.ArgumentParser(description="Catppuccin theme") -parser.add_argument("flavor", - metavar="theme flavor", - type=str, - nargs="+", - choices=["mocha", "frappe", "macchiato", "latte", "all"], - help="Flavor of the theme to apply. Can be frappe, mocha, macchiato, latte") - -parser.add_argument("--name", "-n", - metavar="theme name", - type=str, - default=theme_name, - dest="name", - help="Name of the theme to apply. Defaults to Catppuccin") - -parser.add_argument("--dest", "-d", - metavar="destination", - type=str, - dest="dest", - help="Destination of the files. defaults to releases folder inside the root") - -parser.add_argument("--accent", "-a", - metavar="Accent of the theme", - type=str, - nargs="+", - default=["blue"], - dest="accent", - choices=["rosewater", "flamingo", "pink", "mauve", "red", "maroon", "peach", - "yellow", "green", "teal", "sky", "sapphire", "blue", "lavender", "all"], - help="Accent of the theme. Can include 'rosewater', 'flamingo', 'pink', 'mauve', 'red', 'maroon', \ - 'peach', 'yellow', 'green', 'teal', 'sky', 'sapphire', 'blue', 'lavender'") - -parser.add_argument("--size", "-s", - metavar="Size of the theme", - type=str, - default="standard", - dest="size", - choices=["standard", "compact"], - help="Size variant of the theme. Can be standard or compact") - -parser.add_argument("--tweaks", - metavar="Colloid specific tweaks", - type=str, - default=[], - nargs="+", - dest="tweaks", - choices=["black", "rimless", "normal", "float"], - help="Some specifc tweaks. like black, rimless, normal buttons") - -parser.add_argument("-l", "--link", - help="Link advaita themes to our catppuccin theme", - type=bool, - default=False, - action=argparse.BooleanOptionalAction, - dest="link") - -parser.add_argument("--zip", - help="Zip catppuccin theme", - type=bool, - default=False, - action=argparse.BooleanOptionalAction, - dest="zip") - -parser.add_argument("--recreate-asset", - help="Recreate assets for xfwm4 and such", - type=bool, - default=False, - action=argparse.BooleanOptionalAction, - dest="rec_asset") - -args = parser.parse_args() - -if "all" in args.flavor: - flavors = get_all_flavors() -else: - flavors = args.flavor - -if "all" in args.accent: - accents = get_all_accent() -else: - accents = args.accent - -if args.dest: - dest = args.dest -elif os.geteuid() == 0: # Sudo - dest = "/usr/share/themes" -else: - dest = os.path.expanduser('~') + "/.themes" - -if not os.listdir(work_dir): - subprocess.call("git submodule update --init --recursive", shell=True) - -filename = create_theme(flavors, accents, dest, - args.link, args.name, args.size, args.tweaks, args.zip, args.rec_asset) +#!/usr/bin/env python3 + +import os, zipfile, argparse, logging, io +from pathlib import Path +from dataclasses import dataclass +from urllib.request import urlopen, Request + +logger = logging.getLogger("catppuccin-gtk") +logger.setLevel(logging.DEBUG) +ch = logging.StreamHandler() +formatter = logging.Formatter("[%(name)s] [%(levelname)s] - %(message)s") +ch.setFormatter(formatter) +logger.addHandler(ch) + + +@dataclass +class InstallContext: + flavor: str + accent: str + dest: Path + link: bool + + +def parse_args(): + parser = argparse.ArgumentParser() + parser.add_argument( + "flavor", + type=str, + choices=["mocha", "frappe", "macchiato", "latte"], + help="Flavor of the theme to apply.", + ) + + parser.add_argument( + "accent", + type=str, + default="mauve", + choices=[ + "rosewater", + "flamingo", + "pink", + "mauve", + "red", + "maroon", + "peach", + "yellow", + "green", + "teal", + "sky", + "sapphire", + "blue", + "lavender", + "all", + ], + help="Accent of the theme.", + ) + + parser.add_argument( + "--dest", + "-d", + type=str, + dest="dest", + help="Destination of the files.", + ) + + parser.add_argument( + "--link", + help="Whether to add symlinks for libadwaita", + type=bool, + default=False, + action=argparse.BooleanOptionalAction, + ) + + return parser.parse_args() + + +def build_release_url(ctx: InstallContext) -> str: + repo_root = "https://github.com/catppuccin/gtk/releases/download" + release = "v1.0.0-alpha" + zip_name = f"catppuccin-{ctx.flavor}-{ctx.accent}-standard+default.zip" + + return f"{repo_root}/{release}/{zip_name}" + + +def install(ctx: InstallContext): + url = build_release_url(ctx) + build_info = f"""Installation info: + flavor: {ctx.flavor} + accent: {ctx.accent} + dest: {ctx.dest.absolute()} + link: {ctx.link} + + remote_url: {url}""" + logger.info(build_info) + httprequest = Request(url) + + zip_file = None + logger.info("Starting download...") + with urlopen(httprequest) as response: + logger.info(f"Response status: {response.status}") + zip_file = zipfile.ZipFile(io.BytesIO(response.read())) + logger.info("Download finished, zip is valid") + + logger.info("Verifying download..") + first_bad_file = zip_file.testzip() + if first_bad_file is not None: + logger.error(f'Zip appears to be corrupt, first bad file is "{first_bad_file}"') + return + logger.info("Download verified") + + logger.info("Extracting...") + zip_file.extractall(ctx.dest) + logger.info("Extraction complete") + + if ctx.link: + dir_name = (ctx.dest / f"catppuccin-{ctx.flavor}-{ctx.accent}-standard+default" / 'gtk-4.0').absolute() + gtk4_dir = (Path(os.path.expanduser('~')) / '.config' / 'gtk-4.0').absolute() + os.makedirs(gtk4_dir, exist_ok=True) + + logger.info("Adding symlinks for libadwaita") + logger.info(f'Root: {dir_name}') + logger.info(f'Target: {gtk4_dir}') + os.symlink(dir_name / 'assets', gtk4_dir / 'assets') + os.symlink(dir_name / 'gtk.css', gtk4_dir / 'gtk.css') + os.symlink(dir_name / 'gtk-dark.css', gtk4_dir / 'gtk-dark.css') + + +def main(): + args = parse_args() + dest = Path(os.path.expanduser("~")) / ".local" / "share" / "themes" + os.makedirs(dest, exist_ok=True) + + if args.dest: + dest = Path(args.dest) + + ctx = InstallContext( + flavor=args.flavor, accent=args.accent, dest=dest, link=args.link + ) + + install(ctx) + + logger.info('Theme installation complete!') + + +try: + main() +except Exception as e: + logger.error("Something went wrong when installing the theme:", exc_info=e) diff --git a/patches/colloid/palette.tera b/patches/colloid/palette.tera new file mode 100644 index 00000000..85e024a5 --- /dev/null +++ b/patches/colloid/palette.tera @@ -0,0 +1,87 @@ +--- +whiskers: + version: 2.1.0 + matrix: + - flavor + filename: 'sass-palette-{{ flavor.identifier }}.patch' +--- +{%- set palette = flavor.colors -%} +diff --git a/src/sass/_color-palette-catppuccin-{{ flavor.identifier }}.scss b/src/sass/_color-palette-catppuccin-{{ flavor.identifier }}.scss +new file mode 100644 +index 00000000..8a905942 +--- /dev/null ++++ b/src/sass/_color-palette-catppuccin-{{ flavor.identifier }}.scss +@@ -0,0 +1,72 @@ ++// Default Theme Color Palette ++ ++// Red ++$red-light: #{{ palette.red.hex }}; ++$red-dark: #{{ palette.red | mod(lightness=30) | get(key="hex") }}; ++ ++// Pink ++$pink-light: #{{ palette.pink.hex }}; ++$pink-dark: #{{ palette.pink | mod(lightness=30) | get(key="hex") }}; ++ ++// Purple ++$purple-light: #{{ palette.mauve.hex }}; ++$purple-dark: #{{ palette.mauve | mod(lightness=30) | get(key="hex") }}; ++ ++// Blue ++$blue-light: #{{ palette.blue.hex }}; ++$blue-dark: #{{ palette.blue | mod(lightness=30) | get(key="hex") }}; ++ ++// Teal ++$teal-light: #{{ palette.teal.hex }}; ++$teal-dark: #{{ palette.teal | mod(lightness=30) | get(key="hex") }}; ++ ++// Green ++$green-light: #{{ palette.green.hex }}; ++$green-dark: #{{ palette.green | mod(lightness=30) | get(key="hex") }}; ++ ++// Yellow ++$yellow-light: #{{ palette.yellow.hex }}; ++$yellow-dark: #{{ palette.yellow | mod(lightness=30) | get(key="hex") }}; ++ ++// Orange ++$orange-light: #{{ palette.peach.hex }}; ++$orange-dark: #{{ palette.peach | mod(lightness=30) | get(key="hex") }}; ++ ++// Grey ++$grey-050: #{{ palette.text.hex }}; ++$grey-100: #{{ palette.subtext1.hex }}; ++$grey-150: #{{ palette.subtext1.hex }}; ++$grey-200: #{{ palette.subtext0.hex }}; ++$grey-250: #{{ palette.subtext0.hex }}; ++$grey-300: #{{ palette.overlay1.hex }}; ++$grey-350: #{{ palette.overlay1.hex }}; ++$grey-400: #{{ palette.overlay0.hex }}; ++$grey-450: #{{ palette.overlay0.hex }}; ++$grey-500: #{{ palette.surface2.hex }}; ++$grey-550: #{{ palette.surface2.hex }}; ++$grey-600: #{{ palette.surface1.hex }}; ++$grey-650: #{{ palette.surface1.hex }}; ++$grey-700: #{{ palette.surface0.hex }}; ++$grey-750: #{{ palette.surface0.hex }}; ++$grey-800: #{{ palette.base.hex }}; ++$grey-850: #{{ palette.base.hex }}; ++$grey-900: #{{ palette.crust.hex }}; ++$grey-950: #{{ palette.crust.hex }}; ++ ++// White ++$white: #FFFFFF; ++ ++// Black ++$black: #000000; ++ ++// Button ++$button-close: #{{ palette.red.hex }}; ++$button-max: #{{ palette.green.hex }}; ++$button-min: #{{ palette.yellow.hex }}; ++ ++// Link ++$links: #{{ palette.sky.hex }}; ++ ++// Theme ++$default-light: $purple-light; ++$default-dark: $purple-dark; +{{ '' }} \ No newline at end of file diff --git a/patches/colloid/plank-dark.patch b/patches/colloid/plank-dark.patch new file mode 100644 index 00000000..4fd1684f --- /dev/null +++ b/patches/colloid/plank-dark.patch @@ -0,0 +1,70 @@ +diff --git a/src/main/plank/theme-Dark-Catppuccin/dock.theme b/src/main/plank/theme-Dark-Catppuccin/dock.theme +new file mode 100644 +index 00000000..26a6a747 +--- /dev/null ++++ b/src/main/plank/theme-Dark-Catppuccin/dock.theme +@@ -0,0 +1,64 @@ ++#This file based on: ++#https://git.launchpad.net/plank/tree/data/themes/Default/dock.theme ++ ++[PlankTheme] ++#The roundness of the top corners. ++TopRoundness=16 ++#The roundness of the bottom corners. ++BottomRoundness=0 ++#The thickness (in pixels) of lines drawn. ++LineWidth=0 ++#The color (RGBA) of the outer stroke. ++OuterStrokeColor=0;;0;;0;;0 ++#The starting color (RGBA) of the fill gradient. ++FillStartColor=33;;33;;33;;255 ++#The ending color (RGBA) of the fill gradient. ++FillEndColor=33;;33;;33;;255 ++#The color (RGBA) of the inner stroke. ++InnerStrokeColor=33;;33;;33;;255 ++ ++[PlankDockTheme] ++#The padding on the left/right dock edges, in tenths of a percent of IconSize. ++HorizPadding=2 ++#The padding on the top dock edge, in tenths of a percent of IconSize. ++TopPadding=2 ++#The padding on the bottom dock edge, in tenths of a percent of IconSize. ++BottomPadding=1 ++#The padding between items on the dock, in tenths of a percent of IconSize. ++ItemPadding=2 ++#The size of item indicators, in tenths of a percent of IconSize. ++IndicatorSize=5 ++#The size of the icon-shadow behind every item, in tenths of a percent of IconSize. ++IconShadowSize=0 ++#The height (in percent of IconSize) to bounce an icon when the application sets urgent. ++UrgentBounceHeight=1.6666666666666667 ++#The height (in percent of IconSize) to bounce an icon when launching an application. ++LaunchBounceHeight=0.625 ++#The opacity value (0 to 1) to fade the dock to when hiding it. ++FadeOpacity=1 ++#The amount of time (in ms) for click animations. ++ClickTime=0 ++#The amount of time (in ms) to bounce an urgent icon. ++UrgentBounceTime=600 ++#The amount of time (in ms) to bounce an icon when launching an application. ++LaunchBounceTime=600 ++#The amount of time (in ms) for active window indicator animations. ++ActiveTime=150 ++#The amount of time (in ms) to slide icons into/out of the dock. ++SlideTime=300 ++#The time (in ms) to fade the dock in/out on a hide (if FadeOpacity is < 1). ++FadeTime=250 ++#The time (in ms) to slide the dock in/out on a hide (if FadeOpacity is 1). ++HideTime=250 ++#The size of the urgent glow (shown when dock is hidden), in tenths of a percent of IconSize. ++GlowSize=30 ++#The total time (in ms) to show the hidden-dock urgent glow. ++GlowTime=10000 ++#The time (in ms) of each pulse of the hidden-dock urgent glow. ++GlowPulseTime=2000 ++#The hue-shift (-180 to 180) of the urgent indicator color. ++UrgentHueShift=150 ++#The time (in ms) to move an item to its new position or its addition/removal to/from the dock. ++ItemMoveTime=450 ++#Whether background and icons will unhide/hide with different speeds. The top-border of both will leave/hit the screen-edge at the same time. ++CascadeHide=true diff --git a/patches/colloid/plank-light.patch b/patches/colloid/plank-light.patch new file mode 100644 index 00000000..08908f36 --- /dev/null +++ b/patches/colloid/plank-light.patch @@ -0,0 +1,70 @@ +diff --git a/src/main/plank/theme-Light-Catppuccin/dock.theme b/src/main/plank/theme-Light-Catppuccin/dock.theme +new file mode 100644 +index 00000000..a4029c96 +--- /dev/null ++++ b/src/main/plank/theme-Light-Catppuccin/dock.theme +@@ -0,0 +1,64 @@ ++#This file based on: ++#https://git.launchpad.net/plank/tree/data/themes/Default/dock.theme ++ ++[PlankTheme] ++#The roundness of the top corners. ++TopRoundness=16 ++#The roundness of the bottom corners. ++BottomRoundness=0 ++#The thickness (in pixels) of lines drawn. ++LineWidth=0 ++#The color (RGBA) of the outer stroke. ++OuterStrokeColor=0;;0;;0;;0 ++#The starting color (RGBA) of the fill gradient. ++FillStartColor=242;;242;;242;;255 ++#The ending color (RGBA) of the fill gradient. ++FillEndColor=242;;242;;242;;255 ++#The color (RGBA) of the inner stroke. ++InnerStrokeColor=242;;242;;242;;255 ++ ++[PlankDockTheme] ++#The padding on the left/right dock edges, in tenths of a percent of IconSize. ++HorizPadding=2 ++#The padding on the top dock edge, in tenths of a percent of IconSize. ++TopPadding=2 ++#The padding on the bottom dock edge, in tenths of a percent of IconSize. ++BottomPadding=1 ++#The padding between items on the dock, in tenths of a percent of IconSize. ++ItemPadding=2 ++#The size of item indicators, in tenths of a percent of IconSize. ++IndicatorSize=5 ++#The size of the icon-shadow behind every item, in tenths of a percent of IconSize. ++IconShadowSize=0 ++#The height (in percent of IconSize) to bounce an icon when the application sets urgent. ++UrgentBounceHeight=1.6666666666666667 ++#The height (in percent of IconSize) to bounce an icon when launching an application. ++LaunchBounceHeight=0.625 ++#The opacity value (0 to 1) to fade the dock to when hiding it. ++FadeOpacity=1 ++#The amount of time (in ms) for click animations. ++ClickTime=0 ++#The amount of time (in ms) to bounce an urgent icon. ++UrgentBounceTime=600 ++#The amount of time (in ms) to bounce an icon when launching an application. ++LaunchBounceTime=600 ++#The amount of time (in ms) for active window indicator animations. ++ActiveTime=150 ++#The amount of time (in ms) to slide icons into/out of the dock. ++SlideTime=300 ++#The time (in ms) to fade the dock in/out on a hide (if FadeOpacity is < 1). ++FadeTime=250 ++#The time (in ms) to slide the dock in/out on a hide (if FadeOpacity is 1). ++HideTime=250 ++#The size of the urgent glow (shown when dock is hidden), in tenths of a percent of IconSize. ++GlowSize=30 ++#The total time (in ms) to show the hidden-dock urgent glow. ++GlowTime=10000 ++#The time (in ms) of each pulse of the hidden-dock urgent glow. ++GlowPulseTime=2000 ++#The hue-shift (-180 to 180) of the urgent indicator color. ++UrgentHueShift=150 ++#The time (in ms) to move an item to its new position or its addition/removal to/from the dock. ++ItemMoveTime=450 ++#Whether background and icons will unhide/hide with different speeds. The top-border of both will leave/hit the screen-edge at the same time. ++CascadeHide=true diff --git a/patches/colloid/sass-colors.patch b/patches/colloid/sass-colors.patch new file mode 100644 index 00000000..6367499a --- /dev/null +++ b/patches/colloid/sass-colors.patch @@ -0,0 +1,47 @@ +diff --git a/src/sass/_colors.scss b/src/sass/_colors.scss +index e8366fa0..97fa670c 100644 +--- a/src/sass/_colors.scss ++++ b/src/sass/_colors.scss +@@ -57,9 +57,8 @@ + @else { @return rgba($white, 0.1); } + } + +-@function theme($color) { ++@function theme() { + @if ($variant == 'light') { +- @if ($theme == 'default') { @return $default-dark; } + @if ($theme == 'purple') { @return $purple-dark; } + @if ($theme == 'pink') { @return $pink-dark; } + @if ($theme == 'red') { @return $red-dark; } +@@ -68,8 +67,9 @@ + @if ($theme == 'green') { @return $green-dark; } + @if ($theme == 'teal') { @return $teal-dark; } + @if ($theme == 'grey') { @return $grey-600; } ++ ++ @return $default-dark; + } @else { +- @if ($theme == 'default') { @return $default-light; } + @if ($theme == 'purple') { @return $purple-light; } + @if ($theme == 'pink') { @return $pink-light; } + @if ($theme == 'red') { @return $red-light; } +@@ -78,6 +78,8 @@ + @if ($theme == 'green') { @return $green-light; } + @if ($theme == 'teal') { @return $teal-light; } + @if ($theme == 'grey') { @return $grey-200; } ++ ++ @return $default-light; + } + } + +@@ -113,9 +115,9 @@ + // Basic colors + // + +-$primary: theme(color); ++$primary: theme(); + $drop_target_color: $orange-dark; +-$indicator: theme(color); ++$indicator: theme(); + $titlebar-indicator: if($variant == 'dark', currentColor, $primary); + $inverse-indicator: if($theme == 'grey', $white, $primary); + $applet-primary: if($theme == 'grey' and variant == 'light' and $topbar == 'dark', $grey-200, $primary); diff --git a/patches/colloid/sass-palette-frappe.patch b/patches/colloid/sass-palette-frappe.patch new file mode 100644 index 00000000..048fb79e --- /dev/null +++ b/patches/colloid/sass-palette-frappe.patch @@ -0,0 +1,78 @@ +diff --git a/src/sass/_color-palette-catppuccin-frappe.scss b/src/sass/_color-palette-catppuccin-frappe.scss +new file mode 100644 +index 00000000..8a905942 +--- /dev/null ++++ b/src/sass/_color-palette-catppuccin-frappe.scss +@@ -0,0 +1,72 @@ ++// Default Theme Color Palette ++ ++// Red ++$red-light: #e78284; ++$red-dark: #81191b; ++ ++// Pink ++$pink-light: #f4b8e4; ++$pink-dark: #851567; ++ ++// Purple ++$purple-light: #ca9ee6; ++$purple-dark: #58207a; ++ ++// Blue ++$blue-light: #8caaee; ++$blue-dark: #143686; ++ ++// Teal ++$teal-light: #81c8be; ++$teal-dark: #2f6b63; ++ ++// Green ++$green-light: #a6d189; ++$green-dark: #466f2b; ++ ++// Yellow ++$yellow-light: #e5c890; ++$yellow-dark: #7d5d1d; ++ ++// Orange ++$orange-light: #ef9f76; ++$orange-dark: #8a3910; ++ ++// Grey ++$grey-050: #c6d0f5; ++$grey-100: #b5bfe2; ++$grey-150: #b5bfe2; ++$grey-200: #a5adce; ++$grey-250: #a5adce; ++$grey-300: #838ba7; ++$grey-350: #838ba7; ++$grey-400: #737994; ++$grey-450: #737994; ++$grey-500: #626880; ++$grey-550: #626880; ++$grey-600: #51576d; ++$grey-650: #51576d; ++$grey-700: #414559; ++$grey-750: #414559; ++$grey-800: #303446; ++$grey-850: #303446; ++$grey-900: #232634; ++$grey-950: #232634; ++ ++// White ++$white: #FFFFFF; ++ ++// Black ++$black: #000000; ++ ++// Button ++$button-close: #e78284; ++$button-max: #a6d189; ++$button-min: #e5c890; ++ ++// Link ++$links: #99d1db; ++ ++// Theme ++$default-light: $purple-light; ++$default-dark: $purple-dark; diff --git a/patches/colloid/sass-palette-latte.patch b/patches/colloid/sass-palette-latte.patch new file mode 100644 index 00000000..40da31be --- /dev/null +++ b/patches/colloid/sass-palette-latte.patch @@ -0,0 +1,78 @@ +diff --git a/src/sass/_color-palette-catppuccin-latte.scss b/src/sass/_color-palette-catppuccin-latte.scss +new file mode 100644 +index 00000000..8a905942 +--- /dev/null ++++ b/src/sass/_color-palette-catppuccin-latte.scss +@@ -0,0 +1,72 @@ ++// Default Theme Color Palette ++ ++// Red ++$red-light: #d20f39; ++$red-dark: #900a27; ++ ++// Pink ++$pink-light: #ea76cb; ++$pink-dark: #851567; ++ ++// Purple ++$purple-light: #8839ef; ++$purple-dark: #440b8f; ++ ++// Blue ++$blue-light: #1e66f5; ++$blue-dark: #073693; ++ ++// Teal ++$teal-light: #179299; ++$teal-dark: #148086; ++ ++// Green ++$green-light: #40a02b; ++$green-dark: #317921; ++ ++// Yellow ++$yellow-light: #df8e1d; ++$yellow-dark: #885712; ++ ++// Orange ++$orange-light: #fe640b; ++$orange-dark: #993901; ++ ++// Grey ++$grey-050: #4c4f69; ++$grey-100: #5c5f77; ++$grey-150: #5c5f77; ++$grey-200: #6c6f85; ++$grey-250: #6c6f85; ++$grey-300: #8c8fa1; ++$grey-350: #8c8fa1; ++$grey-400: #9ca0b0; ++$grey-450: #9ca0b0; ++$grey-500: #acb0be; ++$grey-550: #acb0be; ++$grey-600: #bcc0cc; ++$grey-650: #bcc0cc; ++$grey-700: #ccd0da; ++$grey-750: #ccd0da; ++$grey-800: #eff1f5; ++$grey-850: #eff1f5; ++$grey-900: #dce0e8; ++$grey-950: #dce0e8; ++ ++// White ++$white: #FFFFFF; ++ ++// Black ++$black: #000000; ++ ++// Button ++$button-close: #d20f39; ++$button-max: #40a02b; ++$button-min: #df8e1d; ++ ++// Link ++$links: #04a5e5; ++ ++// Theme ++$default-light: $purple-light; ++$default-dark: $purple-dark; diff --git a/patches/colloid/sass-palette-macchiato.patch b/patches/colloid/sass-palette-macchiato.patch new file mode 100644 index 00000000..94e4b064 --- /dev/null +++ b/patches/colloid/sass-palette-macchiato.patch @@ -0,0 +1,78 @@ +diff --git a/src/sass/_color-palette-catppuccin-macchiato.scss b/src/sass/_color-palette-catppuccin-macchiato.scss +new file mode 100644 +index 00000000..8a905942 +--- /dev/null ++++ b/src/sass/_color-palette-catppuccin-macchiato.scss +@@ -0,0 +1,72 @@ ++// Default Theme Color Palette ++ ++// Red ++$red-light: #ed8796; ++$red-dark: #861425; ++ ++// Pink ++$pink-light: #f5bde6; ++$pink-dark: #861467; ++ ++// Purple ++$purple-light: #c6a0f6; ++$purple-dark: #470d8d; ++ ++// Blue ++$blue-light: #8aadf4; ++$blue-dark: #0d388d; ++ ++// Teal ++$teal-light: #8bd5ca; ++$teal-dark: #297166; ++ ++// Green ++$green-light: #a6da95; ++$green-dark: #3a7228; ++ ++// Yellow ++$yellow-light: #eed49f; ++$yellow-dark: #835f17; ++ ++// Orange ++$orange-light: #f5a97f; ++$orange-dark: #8f390b; ++ ++// Grey ++$grey-050: #cad3f5; ++$grey-100: #b8c0e0; ++$grey-150: #b8c0e0; ++$grey-200: #a5adcb; ++$grey-250: #a5adcb; ++$grey-300: #8087a2; ++$grey-350: #8087a2; ++$grey-400: #6e738d; ++$grey-450: #6e738d; ++$grey-500: #5b6078; ++$grey-550: #5b6078; ++$grey-600: #494d64; ++$grey-650: #494d64; ++$grey-700: #363a4f; ++$grey-750: #363a4f; ++$grey-800: #24273a; ++$grey-850: #24273a; ++$grey-900: #181926; ++$grey-950: #181926; ++ ++// White ++$white: #FFFFFF; ++ ++// Black ++$black: #000000; ++ ++// Button ++$button-close: #ed8796; ++$button-max: #a6da95; ++$button-min: #eed49f; ++ ++// Link ++$links: #91d7e3; ++ ++// Theme ++$default-light: $purple-light; ++$default-dark: $purple-dark; diff --git a/patches/colloid/sass-palette-mocha.patch b/patches/colloid/sass-palette-mocha.patch new file mode 100644 index 00000000..c9e20740 --- /dev/null +++ b/patches/colloid/sass-palette-mocha.patch @@ -0,0 +1,78 @@ +diff --git a/src/sass/_color-palette-catppuccin-mocha.scss b/src/sass/_color-palette-catppuccin-mocha.scss +new file mode 100644 +index 00000000..8a905942 +--- /dev/null ++++ b/src/sass/_color-palette-catppuccin-mocha.scss +@@ -0,0 +1,72 @@ ++// Default Theme Color Palette ++ ++// Red ++$red-light: #f38ba8; ++$red-dark: #8c0e32; ++ ++// Pink ++$pink-light: #f5c2e7; ++$pink-dark: #841667; ++ ++// Purple ++$purple-light: #cba6f7; ++$purple-dark: #470d8d; ++ ++// Blue ++$blue-light: #89b4fa; ++$blue-dark: #063d94; ++ ++// Teal ++$teal-light: #94e2d5; ++$teal-dark: #21796a; ++ ++// Green ++$green-light: #a6e3a1; ++$green-dark: #2a7723; ++ ++// Yellow ++$yellow-light: #f9e2af; ++$yellow-dark: #8f650b; ++ ++// Orange ++$orange-light: #fab387; ++$orange-dark: #943c06; ++ ++// Grey ++$grey-050: #cdd6f4; ++$grey-100: #bac2de; ++$grey-150: #bac2de; ++$grey-200: #a6adc8; ++$grey-250: #a6adc8; ++$grey-300: #7f849c; ++$grey-350: #7f849c; ++$grey-400: #6c7086; ++$grey-450: #6c7086; ++$grey-500: #585b70; ++$grey-550: #585b70; ++$grey-600: #45475a; ++$grey-650: #45475a; ++$grey-700: #313244; ++$grey-750: #313244; ++$grey-800: #1e1e2e; ++$grey-850: #1e1e2e; ++$grey-900: #11111b; ++$grey-950: #11111b; ++ ++// White ++$white: #FFFFFF; ++ ++// Black ++$black: #000000; ++ ++// Button ++$button-close: #f38ba8; ++$button-max: #a6e3a1; ++$button-min: #f9e2af; ++ ++// Link ++$links: #89dceb; ++ ++// Theme ++$default-light: $purple-light; ++$default-dark: $purple-dark; diff --git a/scripts/create_theme.py b/scripts/create_theme.py deleted file mode 100644 index 1bae20d7..00000000 --- a/scripts/create_theme.py +++ /dev/null @@ -1,88 +0,0 @@ -from catppuccin import PALETTE -import os -import shutil -import subprocess -from typing import List - -from scripts.patches import recreate_xfwm4_assets -from scripts.recolor import recolor -from scripts.utils import replacetext, zip_multiple_folders -from scripts.var import def_color_map, repo_dir, src_dir, theme_name, work_dir - - -def create_theme(types: List[str], accents: List[str], dest: str, link: bool = False, - name: str = theme_name, size: str = "standard", tweaks=[], zip = False, recreate_assets = False) -> None: - - try: - os.makedirs(dest) # Create our destination directory - except FileExistsError: - pass - - for type in types: - if recreate_assets: - recreate_xfwm4_assets(type) - - for accent in accents: - # Recolor colloid wrt our selection like mocha. latte - recolor(getattr(PALETTE, type), accent) - theme_style: str = "light" if type == "latte" else "dark" - install_cmd: str = f"./install.sh -c {theme_style} -s {size} -n {name} -d {dest} -t {def_color_map[accent]}" - if tweaks: - install_cmd += f" --tweaks {' '.join([tweak for tweak in tweaks])}" - shutil.rmtree(f"{repo_dir}/chrome", ignore_errors=True) - shutil.copytree(f"{src_dir}/other/firefox/chrome", f"{repo_dir}/chrome") - os.chdir(work_dir) - subprocess.call("./build.sh", shell=True) # Rebuild all scss - subprocess.call(install_cmd, shell=True) # Install the theme globally for you - subprocess.call("git reset --hard HEAD", shell=True) # reset colloid repo to original state - - try: - # Rename colloid generated files as per catppuccin - new_filename = dest + \ - f"/{name}-{type.capitalize()}-{size.capitalize()}-{accent.capitalize()}-{theme_style.title()}" - filename = f"{name}" - if def_color_map[accent] != 'default': - filename += f"-{def_color_map[accent].capitalize()}" - filename += f"-{theme_style.capitalize()}" - if size == 'compact': - filename += '-Compact' - try: - shutil.rmtree(new_filename + '-hdpi') - shutil.rmtree(new_filename + '-xhdpi') - shutil.rmtree(new_filename) - except: - pass - os.rename(dest + "/" + filename + '-hdpi', - new_filename + '-hdpi') - os.rename(dest + "/" + filename + '-xhdpi', - new_filename + '-xhdpi') - os.rename(dest + "/" + filename, new_filename) - replacetext(new_filename + '/index.theme', filename, new_filename.split("/")[-1]) - print("Successfully renamed file") - except Exception as e: - print("Failed to rename the files due to:", e) - - if link: - try: - # Attempte relinking all the libadvaita files - subprocess.call( - 'rm -rf "${HOME}/.config/gtk-4.0/"{assets,gtk.css,gtk-dark.css}', shell=True) - HOME = os.path.expanduser('~') - - try: - os.makedirs(f"{HOME}/.config/gtk-4.0") - except FileExistsError: - pass - os.symlink(f"{new_filename}/gtk-4.0/assets", - f"{HOME}/.config/gtk-4.0/assets") - os.symlink(f"{new_filename}/gtk-4.0/gtk.css", - f"{HOME}/.config/gtk-4.0/gtk.css") - os.symlink(f"{new_filename}/gtk-4.0/gtk-dark.css", - f"{HOME}/.config/gtk-4.0/gtk-dark.css") - print("Successfully created symlinks for libadvaita") - except Exception as e: - print("Failed to link due to :", e) - - if zip: - foldernames = [new_filename, new_filename + '-xhdpi', new_filename + '-hdpi'] - zip_multiple_folders(foldernames, new_filename + ".zip", not link) diff --git a/scripts/ctp_colors.py b/scripts/ctp_colors.py deleted file mode 100644 index 9859cfa4..00000000 --- a/scripts/ctp_colors.py +++ /dev/null @@ -1,11 +0,0 @@ -from catppuccin import PALETTE -import dataclasses - - -def get_all_flavors(): - return [f.name for f in dataclasses.fields(PALETTE)] - - -def get_all_accent(): - exclude = ['white', 'black', 'text', 'subtext0', 'subtext1', 'overlay0', 'overlay1', 'overlay2', 'surface0', 'surface1', 'surface2', 'base', 'mantle', 'crust'] - return [f.name for f in dataclasses.fields(PALETTE.latte.colors) if f.name not in exclude] diff --git a/scripts/patches.py b/scripts/patches.py deleted file mode 100644 index 9ccf7d6c..00000000 --- a/scripts/patches.py +++ /dev/null @@ -1,32 +0,0 @@ -import os -import shutil -import subprocess - -from scripts.var import src_dir, repo_dir, work_dir - -def recreate_xfwm4_assets(flavour): - """ - Recolors xfwm4 assets based on the flavour - - Args: - flavour (Flavour): The flavour to recolor - """ - - # Delete assets that already exists and copy new assets file - folders = ["assets", "assets-Light"] - variants = ["", "-Normal"] - sizes = ["", "-hdpi", "-xhdpi"] - assets_folder = f"{src_dir}/assets/xfwm4" - - for folder in folders: - for variant in variants: - for size in sizes: - shutil.rmtree(f"{assets_folder}/{folder}{variant}{size}", ignore_errors=True) - - - patched_asset = f"{repo_dir}/patches/xfwm4/{folder}-Catppuccin-{flavour}{variant}.svg" - shutil.copy(patched_asset, f"{assets_folder}/{folder}{variant}.svg") - - os.chdir(assets_folder) - subprocess.call(f"{assets_folder}/render-assets.sh", shell=True) # Rebuild all assets - os.chdir(work_dir) \ No newline at end of file diff --git a/scripts/recolor.py b/scripts/recolor.py deleted file mode 100644 index 4cb66118..00000000 --- a/scripts/recolor.py +++ /dev/null @@ -1,190 +0,0 @@ -from catppuccin import PALETTE - -from .utils import replacetext, replaceAllText -from .var import (def_accent_dark, def_accent_light, def_color_map, src_dir, work_dir) - - -def recolor_accent(colors, accent: str = "blue"): - """ - Recolors the accent color in a file. - colors: - The flavor to recolor to. Like mocha, frappe, latte, etc. - accent: - The accent color to replace. Defaults to Blue - """ - print(f"Recoloring all accents") - replaceAllText( # Recolor as per base for dark theme. - work_dir, def_accent_dark[def_color_map[accent]], getattr(colors, accent).hex) - replaceAllText( # Recolor as per accent for light. Hard code it as latte - work_dir, def_accent_light[def_color_map[accent]], getattr(PALETTE.latte.colors, accent).hex) - - -def recolor_firefox(colors, accent: str = "blue"): - """ - Recolor the custom gnomish firefox to catpuccin color - """ - firefox_color_file_dark = f"{src_dir}/other/firefox/chrome/Colloid/colors/dark.css" - firefox_color_file_light = f"{src_dir}/other/firefox/chrome/Colloid/colors/light.css" - - replacetext(firefox_color_file_light, "#2e3436", colors.base.hex) - replacetext(firefox_color_file_light, "#fafafa", PALETTE.latte.colors.base.hex) - replacetext(firefox_color_file_light, "#f2f2f2", colors.crust.hex) - replacetext(firefox_color_file_light, "#303030", PALETTE.mocha.colors.base.hex) - replacetext(firefox_color_file_light, "#ffffff", colors.base.hex) - replacetext(firefox_color_file_light, "#5b9bf8", colors.surface0.hex) - replacetext(firefox_color_file_light, "#3c84f7", getattr(colors, accent).hex) - replacetext(firefox_color_file_light, "#dedede", colors.surface1.hex) - replacetext(firefox_color_file_light, "#f0f0f0", colors.surface0.hex) - replacetext(firefox_color_file_light, "#FAFAFA", colors.surface1.hex) - replacetext(firefox_color_file_light, "#fafafa", colors.surface0.hex) - replacetext(firefox_color_file_light, "#323232", colors.mantle.hex) - replacetext(firefox_color_file_light, "#d5d0cc", colors.subtext1.hex) - - # Buttons - replacetext(firefox_color_file_light, "#fd5f51", colors.red.hex) - replacetext(firefox_color_file_light, "#38c76a", colors.green.hex) - replacetext(firefox_color_file_light, "#fdbe04", colors.yellow.hex) - - # Dark - replacetext(firefox_color_file_dark, "#eeeeee", colors.base.hex) - replacetext(firefox_color_file_dark, "#2c2c2c", PALETTE.mocha.colors.base.hex) - replacetext(firefox_color_file_dark, "#242424", colors.crust.hex) - replacetext(firefox_color_file_dark, "#ffffff", PALETTE.latte.colors.base.hex) - replacetext(firefox_color_file_dark, "#383838", colors.base.hex) - replacetext(firefox_color_file_dark, "#3584e4", colors.surface0.hex) - replacetext(firefox_color_file_dark, "#78aeed", getattr(colors, accent).hex) - replacetext(firefox_color_file_dark, "#363636", colors.surface1.hex) - replacetext(firefox_color_file_dark, "#404040", colors.surface0.hex) - replacetext(firefox_color_file_dark, "#4F4F4F", colors.surface1.hex) - replacetext(firefox_color_file_dark, "#444444", colors.surface0.hex) - replacetext(firefox_color_file_dark, "#323232", colors.mantle.hex) - replacetext(firefox_color_file_dark, "#919191", colors.subtext1.hex) - - # Buttons - replacetext(firefox_color_file_dark, "#fd5f51", colors.red.hex) - replacetext(firefox_color_file_dark, "#38c76a", colors.green.hex) - replacetext(firefox_color_file_dark, "#fdbe04", colors.yellow.hex) - -def recolor(flavor, accent: str): - """ - Recolor the theme. currently hard code it frappe - """ - print("Recoloring to suit catppuccin theme") - print("Recoloring accents") - colors = flavor.colors - latte_colors = PALETTE.latte.colors - mocha_colors = PALETTE.mocha.colors - recolor_accent(colors, accent) - print("Recoloring firefox") - recolor_firefox(colors, accent) - - print("MOD: Gtkrc.sh") - replacetext(f"{work_dir}/gtkrc.sh", "background_light='#FFFFFF'", - f"background_light='{latte_colors.base.hex}'") # use latte_base for background_light - replacetext(f"{work_dir}/gtkrc.sh", "titlebar_light='#F2F2F2'", - f"titlebar_light='{latte_colors.crust.hex}'") # use latte_crust for titlebar_light - replacetext(f"{work_dir}/gtkrc.sh", - "titlebar_light='#F2F2F2'", f"titlebar_light='{latte_colors.crust.hex}'") - - if flavor.name == PALETTE.latte.name: - replacetext(f"{work_dir}/gtkrc.sh", "background_dark='#0F0F0F'", - f"background_dark='{mocha_colors.base.hex}'") - replacetext(f"{work_dir}/gtkrc.sh", "background_darker='#121212'", - f"background_darker='{mocha_colors.mantle.hex}'") - replacetext(f"{work_dir}/gtkrc.sh", - "background_alt='#212121'", f"background_alt='{mocha_colors.crust.hex}'") - replacetext(f"{work_dir}/gtkrc.sh", "titlebar_dark='#030303'", - f"titlebar_dark='{mocha_colors.crust.hex}'") - replacetext(f"{work_dir}/gtkrc.sh", "background_dark='#2C2C2C'", - f"background_dark='{mocha_colors.base.hex}'") - replacetext(f"{work_dir}/gtkrc.sh", "background_darker='#3C3C3C'", - f"background_darker='{mocha_colors.mantle.hex}'") - replacetext(f"{work_dir}/gtkrc.sh", - "background_alt='#464646'", f"background_alt='{mocha_colors.crust.hex}'") - replacetext(f"{work_dir}/gtkrc.sh", - "titlebar_dark='#242424'", f"titlebar_dark='{mocha_colors.crust.hex}'") - else: - replacetext(f"{work_dir}/gtkrc.sh", "background_dark='#0F0F0F'", - f"background_dark='{colors.base.hex}'") - replacetext(f"{work_dir}/gtkrc.sh", "background_darker='#121212'", - f"background_darker='{colors.mantle.hex}'") - replacetext(f"{work_dir}/gtkrc.sh", - "background_alt='#212121'", f"background_alt='{colors.crust.hex}'") - replacetext(f"{work_dir}/gtkrc.sh", "titlebar_dark='#030303'", - f"titlebar_dark='{colors.crust.hex}'") - replacetext(f"{work_dir}/gtkrc.sh", "background_dark='#2C2C2C'", - f"background_dark='{colors.base.hex}'") - replacetext(f"{work_dir}/gtkrc.sh", "background_darker='#3C3C3C'", - f"background_darker='{colors.mantle.hex}'") - replacetext(f"{work_dir}/gtkrc.sh", - "background_alt='#464646'", f"background_alt='{colors.crust.hex}'") - replacetext(f"{work_dir}/gtkrc.sh", - "titlebar_dark='#242424'", f"titlebar_dark='{colors.crust.hex}'") - - print("Mod SASS Color_Palette_default") - - # Greys - if flavor.name == PALETTE.latte.name: - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-050: #FAFAFA", f"grey-050: {colors.crust.hex}") - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-100: #F2F2F2", f"grey-100: {colors.mantle.hex}") - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-150: #EEEEEE", f"grey-150: {colors.base.hex}") - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-200: #DDDDDD", f"grey-200: {colors.surface0.hex}") # Surface 0 Late - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-250: #CCCCCC", f"grey-250: {colors.surface1.hex}") # D = Surface 1 Late - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-650: #3C3C3C", f"grey-650: {mocha_colors.surface0.hex}") # H $surface $tooltip - replacetext(f"{src_dir}/sass/_color-palette-default.scss", "grey-700: #2C2C2C", - f"grey-700: {mocha_colors.base.hex}") # G $background; $base; titlebar-backdrop; $popover - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-750: #242424", f"grey-750: {mocha_colors.crust.hex}") # F $base-alt - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-800: #212121", f"grey-800: {mocha_colors.crust.hex}") # E $panel-solid;p - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-850: #121212", f"grey-850: #020202") # H Darknes - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-900: #0F0F0F", f"grey-900: #010101") # G Darknes - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-950: #030303", f"grey-950: #000000") # F Darknes - else: - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-050: #FAFAFA", f"grey-050: {colors.overlay2.hex}") - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-100: #F2F2F2", f"grey-100: {colors.overlay1.hex}") - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-150: #EEEEEE", f"grey-150: {colors.overlay0.hex}") - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-200: #DDDDDD", f"grey-200: {colors.surface2.hex}") # Surface 0 Late - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-250: #CCCCCC", f"grey-250: {colors.surface1.hex}") # D = Surface 1 Late - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-650: #3C3C3C", f"grey-650: {colors.surface0.hex}") # H $surface $tooltip - replacetext(f"{src_dir}/sass/_color-palette-default.scss", "grey-700: #2C2C2C", - f"grey-700: {colors.base.hex}") # G $background; $base; titlebar-backdrop; $popover - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-750: #242424", f"grey-750: {colors.crust.hex}") # F $base-alt - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-800: #212121", f"grey-800: {colors.crust.hex}") # E $panel-solid;p - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-850: #121212", f"grey-850: #020202") # H Darknes - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-900: #0F0F0F", f"grey-900: #010101") # G Darknes - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "grey-950: #030303", f"grey-950: #000000") # F Darknes - - # Make the hover black - replacetext(f"{src_dir}/sass/gtk/_common-3.0.scss", - "if\(\$colorscheme != 'dracula', white, rgba\(black, 0\.5\)\)", "rgba(black, 0.5)") - replacetext(f"{src_dir}/sass/gtk/_common-4.0.scss", - "if\(\$colorscheme != 'dracula', white, rgba\(black, 0\.5\)\)", "rgba(black, 0.5)") - - # Buttons - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "button-close: #fd5f51", f"button-close: {colors.red.hex}") - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "button-max: #38c76a", f"button-max: {colors.green.hex}") - replacetext(f"{src_dir}/sass/_color-palette-default.scss", - "button-min: #fdbe04", f"button-min: {colors.yellow.hex}") diff --git a/scripts/utils.py b/scripts/utils.py deleted file mode 100644 index 2d92eb2e..00000000 --- a/scripts/utils.py +++ /dev/null @@ -1,60 +0,0 @@ -import os -import re -import shutil -import zipfile - - -def replacetext(filepath: str, search_text: str, replace_text: str) -> None: - """ - Helper function to replace the color in the file. - Can be used to replace any text in the file. - - Args: - filepath (str): The file to replace the text in. - search_text (str): The text to be replaced. - replace_text (str): The text to replace with. - - Returns: - None - """ - - try: - with open(filepath, 'r+') as f: - file = f.read() - file = re.sub(search_text, replace_text, file) - f.seek(0) - f.write(file) - f.truncate() - except Exception: - print(f"Failed to recolor {filepath}") - - -def replaceAllText(start_dir: str, search_text: str, replace_text: str) -> None: - for path, _, files in os.walk(os.path.abspath(start_dir)): - for filename in files: - filepath = os.path.join(path, filename) - if filepath.endswith(".png"): - continue - replacetext(filepath, search_text, replace_text) - - -def zipdir(path, ziph): - """ - Takes in a oath of a directory and zips it in a ziph. - Util to zip a directory. - Thanks https://stackoverflow.com/questions/46229764/python-zip-multiple-directories-into-one-zip-file - """ - for root, _, files in os.walk(path): - for file in files: - ziph.write(os.path.join(root, file), - os.path.relpath(os.path.join(root, file), - os.path.join(path, '..'))) - - -def zip_multiple_folders(dir_list, zip_name, remove=True): - zipf = zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED) - for dir in dir_list: - zipdir(dir, zipf) - if remove: - shutil.rmtree(dir) - zipf.close() diff --git a/scripts/var.py b/scripts/var.py deleted file mode 100644 index 46272ca8..00000000 --- a/scripts/var.py +++ /dev/null @@ -1,50 +0,0 @@ -import os - - -repo_dir = os.getcwd() -work_dir = f"{repo_dir}/colloid" -src_dir = f"{work_dir}/src" -tmp_dir = f"{repo_dir}/releases" -theme_name = "Catppuccin" - -# Map catppuccin colors to colloid ones -# These are mostly unused except for resources for lower gtk versions. -# These assets are in png format and I am not really interested right now to recolor them using opencv -# Maybe someone more motivated can follow through -def_color_map = { - 'rosewater': 'pink', - 'flamingo': 'pink', - 'pink': 'pink', - 'mauve': 'purple', - 'red': 'red', - 'maroon': 'red', - 'peach': 'orange', - 'yellow': 'yellow', - 'green': 'green', - 'teal': 'teal', - 'sky': 'teal', - 'sapphire': 'default', - 'blue': 'default', - 'lavender': 'default'} - -def_accent_light = { - 'default': '#3c84f7', - 'purple': '#AB47BC', - 'pink': '#EC407A', - 'red': '#E53935', - 'orange': '#F57C00', - 'yellow': '#FBC02D', - 'green': '#4CAF50', - 'teal': '#009688' -} - -def_accent_dark = { - 'default': '#5b9bf8', - 'purple': '#BA68C8', - 'pink': '#F06292', - 'red': '#F44336', - 'orange': '#FB8C00', - 'yellow': '#FFD600', - 'green': '#66BB6A', - 'teal': '#4DB6AC' -}