Replace content CLI with Textual TUI
This commit is contained in:
1 parent
0d58ddd430
commit
737700a9a8
28 files changed
+2403
-167
No files matched your search
@@ -0,0 +1,87 @@
|
||||
import re
|
||||
|
||||
import jsonfile
|
||||
|
||||
THEMES_FILE = "themes.json"
|
||||
DESKTOP_FILE = "desktop.json"
|
||||
THEME_MODES = ["dark", "light"]
|
||||
COLOR_KEYS = [
|
||||
"accent",
|
||||
"selection",
|
||||
"muted",
|
||||
"background",
|
||||
"dark_background",
|
||||
"lighter_background",
|
||||
"foreground",
|
||||
"red",
|
||||
"yellow",
|
||||
"orange",
|
||||
"green",
|
||||
"cyan",
|
||||
"blue",
|
||||
"magenta",
|
||||
]
|
||||
HEX_COLOR_PATTERN = re.compile(r"^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$")
|
||||
ID_PATTERN = re.compile(r"^[a-z0-9]+(?:-[a-z0-9]+)*$")
|
||||
|
||||
|
||||
def load_themes() -> list[dict]:
|
||||
return jsonfile.load(THEMES_FILE)
|
||||
|
||||
|
||||
def save_themes(themes: list[dict]) -> None:
|
||||
jsonfile.save(THEMES_FILE, themes)
|
||||
|
||||
|
||||
def find_theme(themes: list[dict], theme_id: str) -> dict | None:
|
||||
return next((theme for theme in themes if theme.get("id") == theme_id), None)
|
||||
|
||||
|
||||
def default_theme_id() -> str | None:
|
||||
try:
|
||||
return jsonfile.load(DESKTOP_FILE).get("defaultTheme")
|
||||
except (OSError, ValueError):
|
||||
return None
|
||||
|
||||
|
||||
def set_default_theme(theme_id: str) -> None:
|
||||
desktop = jsonfile.load(DESKTOP_FILE)
|
||||
desktop["defaultTheme"] = theme_id
|
||||
jsonfile.save(DESKTOP_FILE, desktop)
|
||||
|
||||
|
||||
def check_theme(theme: dict) -> dict:
|
||||
if not ID_PATTERN.match(theme.get("id", "")):
|
||||
raise ValueError("Theme id must be lowercase letters, numbers and dashes")
|
||||
if theme.get("mode") not in THEME_MODES:
|
||||
raise ValueError("Mode must be dark or light")
|
||||
for key in COLOR_KEYS:
|
||||
if not HEX_COLOR_PATTERN.match(theme.get("colors", {}).get(key, "")):
|
||||
raise ValueError(f"{key} must be a hex color like #818cf8")
|
||||
for color in theme.get("activeBorder") or []:
|
||||
if not HEX_COLOR_PATTERN.match(color):
|
||||
raise ValueError("Active border colors must be hex colors")
|
||||
return theme
|
||||
|
||||
|
||||
def save_theme(original_id: str | None, theme: dict) -> None:
|
||||
check_theme(theme)
|
||||
themes = load_themes()
|
||||
duplicate = find_theme(themes, theme["id"])
|
||||
if duplicate and theme["id"] != original_id:
|
||||
raise ValueError(f"A theme with the id {theme['id']} already exists")
|
||||
if original_id is None:
|
||||
themes.append(theme)
|
||||
else:
|
||||
index = next(index for index, item in enumerate(themes) if item.get("id") == original_id)
|
||||
themes[index] = theme
|
||||
if original_id != theme["id"] and default_theme_id() == original_id:
|
||||
set_default_theme(theme["id"])
|
||||
save_themes(themes)
|
||||
|
||||
|
||||
def remove_theme(theme_id: str) -> None:
|
||||
if default_theme_id() == theme_id:
|
||||
raise ValueError("That is the default theme. Pick another default first")
|
||||
themes = [theme for theme in load_themes() if theme.get("id") != theme_id]
|
||||
save_themes(themes)
|
||||
Reference in new issue
Block a user