diff options
Diffstat (limited to 'scripts/fix-systemsettings-lua.sh')
| -rwxr-xr-x | scripts/fix-systemsettings-lua.sh | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/scripts/fix-systemsettings-lua.sh b/scripts/fix-systemsettings-lua.sh new file mode 100755 index 00000000..e1b550fc --- /dev/null +++ b/scripts/fix-systemsettings-lua.sh @@ -0,0 +1,229 @@ +#!/usr/bin/env bash +# ================================================== +# KoolDots (2026) +# Project URL: https://github.com/LinuxBeginnings +# License: GNU GPLv3 +# SPDX-License-Identifier: GPL-3.0-or-later +# ================================================== +# Regenerate ~/.config/hypr/configs/system_settings.lua from SystemSettings.conf. + +set -euo pipefail + +CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}" +HYPR_DIR="${CONFIG_HOME}/hypr" +CONFIGS_DIR="${HYPR_DIR}/configs" +LEGACY_DIR="${CONFIGS_DIR}/LegacyConfigs" +SYSTEM_SETTINGS_CONF="${CONFIGS_DIR}/SystemSettings.conf" +SYSTEM_SETTINGS_LUA="${CONFIGS_DIR}/system_settings.lua" + +python3 - <<'PY' +from pathlib import Path +import os +import re + +HEADER = """-- ================================================== +-- KoolDots (2026) +-- Project URL: https://github.com/LinuxBeginnings +-- License: GNU GPLv3 +-- SPDX-License-Identifier: GPL-3.0-or-later +-- ================================================== +""" + +config_home = Path(os.getenv("XDG_CONFIG_HOME") or (Path.home() / ".config")) +hypr_dir = config_home / "hypr" +configs_dir = hypr_dir / "configs" +legacy_dir = configs_dir / "LegacyConfigs" +system_settings_path = configs_dir / "SystemSettings.conf" +output_path = configs_dir / "system_settings.lua" + +def strip_comment(line: str) -> str: + return line.split("#", 1)[0].strip() + +def lua_string(value: str) -> str: + return '"' + value.replace("\\", "\\\\").replace('"', '\\"') + '"' + +def scalar(value: str, *, bool_words: bool = True) -> str: + value = value.strip() + lower = value.lower() + if bool_words and lower in {"on", "true", "yes"}: + return "true" + if bool_words and lower in {"off", "false", "no"}: + return "false" + if re.fullmatch(r"[-+]?\d+(\.\d+)?", value): + return value + return lua_string(value) + +def render_table(value, indent=4): + lines = [] + for key, child in value.items(): + if isinstance(child, dict): + lines.append(" " * indent + f"{key} = {{") + lines.extend(render_table(child, indent + 2)) + lines.append(" " * indent + "},") + else: + lines.append(" " * indent + f"{key} = {scalar(str(child))},") + return lines + +def latest_legacy_file(path: Path): + if not legacy_dir.is_dir(): + return None + candidates = [] + for snapshot in sorted(legacy_dir.iterdir()): + if not snapshot.is_dir(): + continue + candidate = snapshot / path.name + if candidate.is_file(): + candidates.append(candidate) + return candidates[-1] if candidates else None + +def parse_hyprlang_sections(path: Path): + sections = {} + if path is None or not path.exists(): + return sections + stack = [sections] + for raw in path.read_text(encoding="utf-8", errors="ignore").splitlines(): + line = strip_comment(raw) + if not line: + continue + if line.startswith("source"): + continue + if line.endswith("{"): + name = line[:-1].strip().replace("-", "_") + if not name or name.startswith("$"): + continue + current = stack[-1] + target = current.setdefault(name, {}) + stack.append(target) + continue + if line == "}": + if len(stack) > 1: + stack.pop() + continue + if "=" in line: + key, value = [part.strip() for part in line.split("=", 1)] + if not key or key.startswith("$"): + continue + key = key.replace("-", "_") + container = stack[-1] + parts = [part.replace("-", "_") for part in key.split(".") if part] + for part in parts[:-1]: + container = container.setdefault(part, {}) + container[parts[-1]] = value + return sections + +def parse_scripts_dir(path: Path): + if path is None or not path.exists(): + return None + for raw in path.read_text(encoding="utf-8", errors="ignore").splitlines(): + line = strip_comment(raw) + if not line: + continue + match = re.match(r"^\$scriptsDir\s*=\s*(.+)$", line) + if match: + value = match.group(1).strip().strip('"').strip("'") + return value + return None + +def parse_gestures(path: Path): + simple = [] + complex_entries = [] + if path is None or not path.exists(): + return simple, complex_entries + for raw in path.read_text(encoding="utf-8", errors="ignore").splitlines(): + line = strip_comment(raw) + if not line: + continue + match = re.match(r"^gesture\s*=\s*(.+)$", line) + if not match: + continue + payload = match.group(1).strip() + parts = [part.strip() for part in payload.split(",")] + if len(parts) >= 3 and parts[2] == "workspace": + try: + fingers = int(parts[0]) + except ValueError: + complex_entries.append(payload) + continue + simple.append({"fingers": fingers, "direction": parts[1], "action": "workspace"}) + else: + complex_entries.append(payload) + return simple, complex_entries + +source_path = system_settings_path if system_settings_path.exists() else latest_legacy_file(system_settings_path) + +lines = [ + "-- System Settings (auto-generated).", + "-- This file keeps migrated settings split from user overrides.", + "-- Add only Lua entries here.", + "-- Example:", + "-- hl.config({ general = { gaps_in = 4, gaps_out = 8 } })", + "", +] + +if source_path is None: + lines.append("-- No active entries were found in SystemSettings.conf.") +else: + scripts_dir = parse_scripts_dir(source_path) + if scripts_dir: + lines.append(f"local scriptsDir = {lua_string(scripts_dir)}") + lines.append("") + + sections = parse_hyprlang_sections(source_path) + gestures_section = sections.pop("gestures", None) + if gestures_section and "gesture" in gestures_section: + gestures_section.pop("gesture", None) + + ordered_sections = [ + "dwindle", + "master", + "scrolling", + "general", + "input", + "gestures", + "misc", + "binds", + "xwayland", + "render", + "cursor", + ] + for section in ordered_sections: + if section == "gestures": + data = gestures_section + elif section == "misc": + data = sections.get(section) or {} + if "force_default_wallpaper" not in data: + data["force_default_wallpaper"] = "false" + else: + data = sections.get(section) + if not data: + continue + lines.append("hl.config({") + lines.append(f" {section} = {{") + lines.extend(render_table(data, indent=4)) + lines.append(" },") + lines.append("})") + lines.append("") + + simple_gestures, complex_gestures = parse_gestures(source_path) + for spec in simple_gestures: + lines.extend([ + "hl.gesture({", + f" fingers = {spec['fingers']},", + f" direction = {lua_string(spec['direction'])},", + f" action = {lua_string(spec['action'])},", + "})", + "", + ]) + + if complex_gestures: + lines.append("-- Complex dispatcher gestures from SystemSettings.conf are pending explicit Lua API parity:") + for entry in complex_gestures: + lines.append(f"-- gesture = {entry}") + lines.append("") + +content = "\n".join(lines).rstrip() + "\n" +if not content.startswith(HEADER): + content = HEADER + "\n" + content.lstrip("\n") +output_path.write_text(content, encoding="utf-8") +print(f"[OK] Wrote {output_path}") +PY |
