- Light theme uses Papirus-Light: the panel icons of Papirus are #dfdfdf, made for dark panels (xsettings, theme index, login screen). - das-panel-icon help/-h/--help print usage instead of setting an icon; unknown options are rejected. - New packages publisher (publish) and deployer (deploy) on the desktop image: config in ~/.config/<name>/ (neutral example copied on first run), history in ~/.local/state/<name>/. - das-theme 0.3.0, das-settings 0.6.0. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
82 lines
3.1 KiB
Python
82 lines
3.1 KiB
Python
"""Guess an [[app]] block for a local project: Android (+ electron desktop), Go, or any dir with builds."""
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import re
|
|
from pathlib import Path
|
|
|
|
from . import packages
|
|
from .config import App
|
|
|
|
_ROOT_NAME = re.compile(r"""rootProject\.name\s*=\s*["']([^"']+)["']""")
|
|
_GO_VERSION = re.compile(r'Version\s*=\s*"')
|
|
|
|
|
|
def _rel(p: Path, base: Path) -> str:
|
|
return str(p.relative_to(base))
|
|
|
|
|
|
def _home(p: Path) -> str:
|
|
home = Path.home()
|
|
return "~/" + str(p.relative_to(home)) if p.is_relative_to(home) else str(p)
|
|
|
|
|
|
def _site_name(raw: str) -> str:
|
|
"""A name apps.jsp groups correctly: no spaces, no _<digit>."""
|
|
name = re.sub(r"[^A-Za-z0-9_.\-]+", "", raw)
|
|
return re.sub(r"[_-]v?(?=\d)", "", name) or "App"
|
|
|
|
|
|
def _name_from_builds(files: list[Path]) -> str:
|
|
for f in files:
|
|
m = packages.LOCAL_VERSION.search(f.name)
|
|
if m and m.start() > 0:
|
|
return f.name[:m.start()]
|
|
return ""
|
|
|
|
|
|
def _first(base: Path, *names: str) -> Path | None:
|
|
for n in names:
|
|
if (base / n).is_file():
|
|
return base / n
|
|
return None
|
|
|
|
|
|
def new_app(path: Path, name: str | None = None) -> App:
|
|
path = path.expanduser().resolve()
|
|
# no build command is guessed: Android Studio signs into app/release, gradle into app/build/outputs
|
|
globs, builds, version_file = [], [], ""
|
|
|
|
gradle = _first(path, "app/build.gradle.kts", "app/build.gradle")
|
|
if gradle:
|
|
version_file = _rel(gradle, path)
|
|
# both places of a signed release APK: the best build of the two is published
|
|
for d in ("app/release", "app/build/outputs/apk/release"):
|
|
globs.append(f"{d}/*.apk")
|
|
builds += sorted((path / d).glob("*.apk"))
|
|
dist = path / "desktop/dist"
|
|
if dist.is_dir():
|
|
for ext in (".AppImage", ".deb", ".rpm", ".exe", ".msi", ".dmg"):
|
|
if any(dist.glob(f"*{ext}")):
|
|
globs.append(f"desktop/dist/*{ext}")
|
|
else:
|
|
go_version = next((p for p in path.glob("internal/version/*.go")
|
|
if _GO_VERSION.search(p.read_text(errors="replace"))), None)
|
|
if go_version:
|
|
version_file = _rel(go_version, path)
|
|
elif (path / "pyproject.toml").is_file():
|
|
version_file = "pyproject.toml"
|
|
for d in ("build", "dist", "bin", "release"):
|
|
for f in sorted((path / d).glob("*")) if (path / d).is_dir() else []:
|
|
if f.is_file() and packages.kind_of(f.name, os.access(f, os.X_OK)):
|
|
builds.append(f)
|
|
k = packages.kind_of(f.name)
|
|
globs.append(f"{d}/*{k.ext}" if k and k.ext else f"{d}/{f.name}")
|
|
globs = list(dict.fromkeys(globs))
|
|
|
|
if not name:
|
|
settings = _first(path, "settings.gradle.kts", "settings.gradle")
|
|
m = _ROOT_NAME.search(settings.read_text(errors="replace")) if settings else None
|
|
name = _name_from_builds(builds) or (m.group(1) if m else "") or path.name
|
|
return App(name=_site_name(name), src=_home(path), packages=globs, version_file=version_file)
|