diff options
| author | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-06-11 17:37:04 +1000 |
|---|---|---|
| committer | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-06-11 17:37:04 +1000 |
| commit | dc855e1b01e9b4526927b8bd69daca733afd97c2 (patch) | |
| tree | 38adb17eb316e92d70b64df6824d3ad91901028f /src/caelestia/utils | |
| parent | parser: print help when no args (diff) | |
| download | caelestia-cli-dc855e1b01e9b4526927b8bd69daca733afd97c2.tar.gz caelestia-cli-dc855e1b01e9b4526927b8bd69daca733afd97c2.tar.bz2 caelestia-cli-dc855e1b01e9b4526927b8bd69daca733afd97c2.zip | |
internal: refactor scheme
Also use a single file to store scheme data
Diffstat (limited to 'src/caelestia/utils')
| -rw-r--r-- | src/caelestia/utils/hypr.py | 2 | ||||
| -rw-r--r-- | src/caelestia/utils/paths.py | 13 | ||||
| -rw-r--r-- | src/caelestia/utils/scheme.py | 194 |
3 files changed, 208 insertions, 1 deletions
diff --git a/src/caelestia/utils/hypr.py b/src/caelestia/utils/hypr.py index d829f22..621e28e 100644 --- a/src/caelestia/utils/hypr.py +++ b/src/caelestia/utils/hypr.py @@ -5,7 +5,7 @@ import socket socket_path = f"{os.getenv('XDG_RUNTIME_DIR')}/hypr/{os.getenv('HYPRLAND_INSTANCE_SIGNATURE')}/.socket.sock" -def message(msg: str, json: bool = True) -> str or dict[str, any]: +def message(msg: str, json: bool = True) -> str | dict[str, any]: with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock: sock.connect(socket_path) diff --git a/src/caelestia/utils/paths.py b/src/caelestia/utils/paths.py new file mode 100644 index 0000000..aff6ea0 --- /dev/null +++ b/src/caelestia/utils/paths.py @@ -0,0 +1,13 @@ +import os +from pathlib import Path + +config_dir = Path(os.getenv("XDG_CONFIG_HOME", Path.home() / ".config")) +data_dir = Path(os.getenv("XDG_DATA_HOME", Path.home() / ".local/share")) +state_dir = Path(os.getenv("XDG_STATE_HOME", Path.home() / ".local/state")) + +c_config_dir = config_dir / "caelestia" +c_data_dir = data_dir / "caelestia" +c_state_dir = state_dir / "caelestia" + +scheme_path = c_state_dir / "scheme.json" +scheme_data_path = Path(__file__).parent.parent / "data/schemes" diff --git a/src/caelestia/utils/scheme.py b/src/caelestia/utils/scheme.py index e69de29..79a0c21 100644 --- a/src/caelestia/utils/scheme.py +++ b/src/caelestia/utils/scheme.py @@ -0,0 +1,194 @@ +import json +from pathlib import Path + +from caelestia.utils.paths import scheme_data_path, scheme_path + + +class Scheme: + _name: str + _flavour: str + _mode: str + _variant: str + _colours: dict[str, str] + + def __init__(self, json: dict[str, any] | None) -> None: + if json is None: + self._name = "catppuccin" + self._flavour = "mocha" + self._mode = "dark" + self._variant = "tonalspot" + self._colours = read_colours_from_file(self.get_colours_path()) + else: + self._name = json["name"] + self._flavour = json["flavour"] + self._mode = json["mode"] + self._variant = json["variant"] + self._colours = json["colours"] + + @property + def name(self) -> str: + return self._name + + @name.setter + def name(self, name: str) -> None: + if name == self._name: + return + + if name not in get_scheme_names(): + raise ValueError(f"Invalid scheme name: {name}") + + self._name = name + self._check_flavour() + self._check_mode() + self._update_colours() + self.save() + + @property + def flavour(self) -> str: + return self._flavour + + @flavour.setter + def flavour(self, flavour: str) -> None: + if flavour == self._flavour: + return + + if flavour not in get_scheme_flavours(): + raise ValueError(f"Invalid scheme flavour: {flavour}") + + self._flavour = flavour + self._check_mode() + self._update_colours() + self.save() + + @property + def mode(self) -> str: + return self._mode + + @mode.setter + def mode(self, mode: str) -> None: + if mode == self._mode: + return + + if mode not in get_scheme_modes(): + raise ValueError(f"Invalid scheme mode: {mode}") + + self._mode = mode + self._update_colours() + self.save() + + @property + def variant(self) -> str: + return self._variant + + @variant.setter + def variant(self, variant: str) -> None: + self._variant = variant + + @property + def colours(self) -> dict[str, str]: + return self._colours + + def get_colours_path(self) -> Path: + return (scheme_data_path / self.name / self.flavour / self.mode).with_suffix(".txt") + + def save(self) -> None: + scheme_path.parent.mkdir(parents=True, exist_ok=True) + with scheme_path.open("w") as f: + json.dump( + { + "name": self.name, + "flavour": self.flavour, + "mode": self.mode, + "variant": self.variant, + "colours": self.colours, + }, + f, + ) + + def _check_flavour(self) -> None: + global scheme_flavours + scheme_flavours = None + if self._flavour not in get_scheme_flavours(): + self._flavour = get_scheme_flavours()[0] + + def _check_mode(self) -> None: + global scheme_modes + scheme_modes = None + if self._mode not in get_scheme_modes(): + self._mode = get_scheme_modes()[0] + + def _update_colours(self) -> None: + self._colours = read_colours_from_file(self.get_colours_path()) + + +scheme_variants = [ + "tonalspot", + "vibrant", + "expressive", + "fidelity", + "fruitsalad", + "monochrome", + "neutral", + "rainbow", + "content", +] + +scheme_names: list[str] = None +scheme_flavours: list[str] = None +scheme_modes: list[str] = None + +scheme: Scheme = None + + +def read_colours_from_file(path: Path) -> dict[str, str]: + return {k.strip(): v.strip() for k, v in (line.split(" ") for line in path.read_text().splitlines())} + + +def get_scheme_path() -> Path: + return get_scheme().get_colours_path() + + +def get_scheme() -> Scheme: + global scheme + + if scheme is None: + try: + scheme_json = json.loads(scheme_path.read_text()) + scheme = Scheme(scheme_json) + except (IOError, json.JSONDecodeError): + scheme = Scheme(None) + + return scheme + + +def get_scheme_names() -> list[str]: + global scheme_names + + if scheme_names is None: + scheme_names = [f.name for f in scheme_data_path.iterdir() if f.is_dir()] + scheme_names.append("dynamic") + + return scheme_names + + +def get_scheme_flavours() -> list[str]: + global scheme_flavours + + if scheme_flavours is None: + name = get_scheme().name + if name == "dynamic": + scheme_flavours = ["default", "alt1", "alt2"] + else: + scheme_flavours = [f.name for f in (scheme_data_path / name).iterdir() if f.is_dir()] + + return scheme_flavours + + +def get_scheme_modes() -> list[str]: + global scheme_modes + + if scheme_modes is None: + scheme = get_scheme() + scheme_modes = [f.stem for f in (scheme_data_path / scheme.name / scheme.flavour).iterdir() if f.is_file()] + + return scheme_modes |