macOS support (code only, no build yet)

This commit is contained in:
sarah committed 2026-10-14 13:18:20 +02:00
1 parent 1feb6d4336
commit ca04dcd4a7
17 files changed
+572 -126

No files matched your search

+19 -11
View File
@@ -3,8 +3,9 @@ and Hooks.py next to it. See README.md for the full manifest format.
A manifest's Platforms (default ["Linux"]) says where the program runs; each
SaraSuite only lists the programs for its own system. Any list item can also
carry Platform = "Linux" or "Windows" to only apply there (e.g. desktop
entries on Linux, Start Menu shortcuts on Windows); others are dropped at load."""
carry Platform = "Linux", "Windows" or "macOS" to only apply there (e.g.
desktop entries on Linux, Start Menu shortcuts on Windows, app bundles on
macOS); others are dropped at load."""
import importlib.util
import re
@@ -16,7 +17,7 @@ from typing import Optional
import tomlkit
from Core import (
AutostartDir, CacheHome, ConfigHome, CurrentDesktop, DataHome, HasSystemd, Home, IsWindows, LoadConfig,
AutostartDir, CacheHome, ConfigHome, CurrentDesktop, DataHome, HasSystemd, Home, IsLinux, IsMac, IsWindows, LoadConfig,
Platform, ProgramsDir, SharedConfigDir, StartMenuDir, StartupDir, UserPortalsSupported,
)
@@ -86,10 +87,11 @@ class IniEdit:
@dataclass
class Service:
"""A background service. Linux with systemd: a --user Unit (placed by a
Template). Windows, and Linux without systemd (runit, OpenRC, ...):
Template). Windows, macOS, and Linux without systemd (runit, OpenRC, ...):
Script (relative to the app folder) run by ServiceRun.py in WorkingDir,
at login through a Startup-folder shortcut / an XDG autostart entry
(Services.py), so a Linux service gives both Unit and Name/Script."""
at login through a Startup-folder shortcut / a LaunchAgent / an XDG
autostart entry (Services.py), so a Linux service gives both Unit and
Name/Script."""
Unit: str = ""
Option: str = "" # enabled + started only while this option is ticked
@@ -109,9 +111,12 @@ class Service:
@dataclass
class Shortcut:
"""Windows: a Start Menu shortcut running Script (relative to the app
folder) with the program's pythonw.exe, from the app folder, with Icon
(a PNG in the app folder, turned into an .ico)."""
"""A launcher in the system's app list running Script (relative to the
app folder) with the program's Python, from the app folder, with Icon (a
PNG in the app folder):
- Windows: a Start Menu shortcut (pythonw.exe; the icon becomes an .ico);
- macOS: an app bundle, ~/Applications/<Name>.app (the icon becomes an .icns).
Linux uses a desktop entry Template instead."""
Name: str
Script: str
@@ -235,6 +240,9 @@ class Program:
}
if IsWindows:
Context.update(StartMenuDir=str(StartMenuDir), StartupDir=str(StartupDir))
elif IsMac:
Context.update(ApplicationsDir=str(Home / "Applications"),
LaunchAgentsDir=str(Home / "Library" / "LaunchAgents"))
else:
Context.update(
SystemdUserDir=str(ConfigHome / "systemd" / "user"),
@@ -306,7 +314,7 @@ def LoadProgram(Folder: Path) -> Program:
Configs=[ConfigFile(**Item) for Item in _ForPlatform(Data.get("Configs", []))],
IniEdits=[IniEdit(**Item) for Item in _ForPlatform(Data.get("IniEdits", []))],
Services=[Service(**Item) for Item in _ForPlatform(Data.get("Services", []))],
RestartUnits=[] if IsWindows else Data.get("RestartUnits", []),
RestartUnits=Data.get("RestartUnits", []) if IsLinux else [],
Leftovers=[Leftover(**Item) for Item in _ForPlatform(Data.get("Leftovers", []))],
Shortcuts=[Shortcut(**Item) for Item in _ForPlatform(Data.get("Shortcuts", []))],
Platforms=Data.get("Platforms", ["Linux"]),
@@ -330,7 +338,7 @@ def LoadPrograms() -> list[Program]:
Loaded = _LoadFrom(ManifestsDir())
except Exception:
Loaded = _LoadFrom(BundledManifestsDir)
# Only the programs that run on this system (the .exe lists Windows ones).
# Only the programs that run on this system (the .exe lists Windows ones, the Mac app macOS ones).
Loaded = [Current for Current in Loaded if Platform in Current.Platforms]
Names = {Current.Name for Current in Loaded}
Ordered = []