ProPresenter updates are safe: any installed copy counts as running, the newest version opens
- newest_of picks by CFBundleShortVersionString, not file name (ProPresenter.app sorted after ProPresenter 20.1.app) - mac_start takes newest_of; auto-setup uses it for programs on the Companion Mac - WS and SC switched over; NA's ProP restart re-rendered (same pick today) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+21
-3
@@ -64,6 +64,22 @@ def mac_quit(process, wait_seconds, force, stop_children=False):
|
||||
return s
|
||||
|
||||
|
||||
def newest_app(pattern):
|
||||
"""APP=... the newest installed copy by its own version number (CFBundleShortVersionString), not by
|
||||
file name: "ProPresenter.app" sorts after "ProPresenter 20.1.app" by name (2026-10-21, before the
|
||||
Southcoast/Woonsocket ProPresenter update)."""
|
||||
return ("APP=$(for a in %s; do [ -d \"$a\" ] && printf '%%s|%%s\\n' \"$(defaults read \"$a/Contents/Info\" "
|
||||
"CFBundleShortVersionString 2>/dev/null)\" \"$a\"; done | sort -t '|' -k1,1V | tail -1 | cut -d '|' -f2-); "
|
||||
% str(pattern).strip())
|
||||
|
||||
|
||||
def app_match(pattern, process):
|
||||
"""A pgrep -f pattern for the program from any copy matching an /Applications glob (never its helpers)."""
|
||||
import re as _re
|
||||
parts = [_re.escape(x) for x in str(pattern).split("*")]
|
||||
return "[^/]*".join(parts).replace("\\ ", " ") + "/Contents/MacOS/" + _re.escape(process).replace("\\ ", " ") + "$"
|
||||
|
||||
|
||||
def mac_open(app, background=False, arg=None):
|
||||
"""open -a Name / open /path/App.app (+ -g to stay in the background)."""
|
||||
app = str(app)
|
||||
@@ -109,8 +125,10 @@ TEMPLATES = {
|
||||
"words": "Start a Mac program if it is not running",
|
||||
"os": "mac", "start_only": True,
|
||||
"params": [P_HOST, ("process", "Process name", "As pgrep sees it (Activity Monitor's process name).", "str", None),
|
||||
("app", "App to open", "Its name, or the full /Applications/... path.", "str", None)],
|
||||
"render": lambda p, cfg: "pgrep -xq %s || %s" % (q(p["process"]), mac_open(p["app"])),
|
||||
("app", "App to open", "Its name, the full /Applications/... path, or $APP with 'newest of' below.", "str", None),
|
||||
("newest_of", "Newest of", "A pattern like /Applications/ProPresenter*.app: the newest installed version opens.", "str", "")],
|
||||
"render": lambda p, cfg: ("pgrep -xq %s || { %s%s; }" % (q(p["process"]), newest_app(p["newest_of"]), mac_open("$APP"))
|
||||
if p.get("newest_of") else "pgrep -xq %s || %s" % (q(p["process"]), mac_open(p["app"]))),
|
||||
"suggest": lambda p, cfg: "start %s if it is not running" % p["app"],
|
||||
},
|
||||
"mac_restart": {
|
||||
@@ -123,7 +141,7 @@ TEMPLATES = {
|
||||
("background", "Open it in the background", "No window comes to the front.", "bool", False),
|
||||
("stop_children", "Also stop everything it started", "Its helper processes (a translation server, say).", "bool", False),
|
||||
("newest_of", "Newest of", "A pattern like /Applications/ProPresenter*.app: the newest installed version opens.", "str", "")],
|
||||
"render": lambda p, cfg: (("APP=$(ls -d %s | sort -V | tail -1); " % str(p["newest_of"]).strip()) if p.get("newest_of") else "")
|
||||
"render": lambda p, cfg: (newest_app(p["newest_of"]) if p.get("newest_of") else "")
|
||||
+ mac_quit(p["process"], p.get("wait_seconds", 10), p.get("force", True), p.get("stop_children", False))
|
||||
+ mac_open("$APP" if p.get("newest_of") else p["app"], p.get("background", False)),
|
||||
"suggest": lambda p, cfg: "restart %s" % (p["app"] if not p.get("newest_of") else "%s (newest installed)" % p["process"]),
|
||||
|
||||
Reference in New Issue
Block a user