Private
Public Access
78 lines
2.9 KiB
Python
78 lines
2.9 KiB
Python
from __future__ import annotations
|
|
|
|
import sys
|
|
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
|
|
from src.paths import get_layouts_dir
|
|
from src.result_types import ErrorInfo, ErrorKind, Result
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class LayoutFile:
|
|
"""A bundled Manual Slop layout asset (.ini). Stores raw INI text
|
|
intended to be installed to cwd/manualslop_layout.ini by App._post_init
|
|
when the user's INI is empty or missing. The raw text is opaque to
|
|
this module; structure parsing (ImGui sections, [Window] entries)
|
|
is the consumer's responsibility."""
|
|
name: str
|
|
raw_text: str
|
|
source_path: Path
|
|
scope: str
|
|
|
|
|
|
def load_layouts_from_file(path: Path, scope: str) -> dict[str, LayoutFile]:
|
|
"""Load ONE layout file and return a 1-entry dict. Public API matches
|
|
themes' load_themes_from_toml shape (dict out)."""
|
|
out: dict[str, LayoutFile] = {}
|
|
if not path.exists() or not path.is_file():
|
|
return out
|
|
try:
|
|
raw = path.read_text(encoding="utf-8", errors="replace")
|
|
except OSError as e:
|
|
_layout_err = Result(data=None, errors=[ErrorInfo(kind=ErrorKind.INVALID_INPUT, message=f"failed to read layout {path}: {e}", source="layouts.load_layouts_from_file", original=e)])
|
|
print(f"warning: failed to read {path}: {e}", file=sys.stderr)
|
|
return out
|
|
out[path.stem] = LayoutFile(name=path.stem, raw_text=raw, source_path=path, scope=scope)
|
|
return out
|
|
|
|
|
|
def load_layouts_from_dir(path: Path, scope: str) -> dict[str, LayoutFile]:
|
|
"""Load every .ini layout in `path`. Empty dict on missing dir
|
|
or all-skip (per the 'delete to turn off' pattern in
|
|
conductor/code_styleguides/feature_flags.md). Per-file errors are
|
|
drained via Result + stderr warn, mirroring
|
|
src/theme_models.py:load_themes_from_dir."""
|
|
out: dict[str, LayoutFile] = {}
|
|
if not path.exists() or not path.is_dir():
|
|
return out
|
|
for child in sorted(path.iterdir()):
|
|
if not child.is_file():
|
|
continue
|
|
if child.suffix.lower() != ".ini":
|
|
continue
|
|
try:
|
|
raw = child.read_text(encoding="utf-8", errors="replace")
|
|
except OSError as e:
|
|
_layout_err = Result(data=None, errors=[ErrorInfo(kind=ErrorKind.INVALID_INPUT, message=f"failed to read layout {child}: {e}", source="layouts.load_layouts_from_dir", original=e)])
|
|
print(f"warning: failed to read {child}: {e}", file=sys.stderr)
|
|
continue
|
|
layout = LayoutFile(name=child.stem, raw_text=raw, source_path=child, scope=scope)
|
|
out[layout.name] = layout
|
|
return out
|
|
|
|
|
|
_LAYOUTS_CACHE: dict[str, LayoutFile] = {}
|
|
|
|
|
|
def load_layouts_from_disk() -> dict[str, LayoutFile]:
|
|
"""Load all bundled layouts from the global layouts dir
|
|
(resolved via src/paths.py:get_layouts_dir()). Cached at the
|
|
module level; callers iterate the returned dict. The 'delete to
|
|
turn off' guarantee: a missing or empty layouts/ dir returns {}."""
|
|
global _LAYOUTS_CACHE
|
|
layouts_dir = get_layouts_dir()
|
|
_LAYOUTS_CACHE = load_layouts_from_dir(layouts_dir, scope="global")
|
|
return _LAYOUTS_CACHE
|