mac support
This commit is contained in:
+51
-7
@@ -8,6 +8,12 @@ import sys
|
||||
from pathlib import Path
|
||||
from typing import Literal
|
||||
|
||||
MACOS_EXECUTABLE_DIRECTORIES = (
|
||||
Path("/opt/homebrew/bin"),
|
||||
Path("/usr/local/bin"),
|
||||
Path("/Library/TeX/texbin"),
|
||||
)
|
||||
|
||||
WINDOWS_RESERVED_NAMES = {
|
||||
"CON",
|
||||
"PRN",
|
||||
@@ -71,6 +77,36 @@ def safe_filename(value: str, fallback: str = "Unknown") -> str:
|
||||
return cleaned
|
||||
|
||||
|
||||
def add_platform_executable_paths(
|
||||
environment: dict[str, str], platform_name: str | None = None
|
||||
) -> dict[str, str]:
|
||||
"""Expose common desktop-installed executables to child processes."""
|
||||
result = dict(environment)
|
||||
if (platform_name or sys.platform) != "darwin":
|
||||
return result
|
||||
existing = result.get("PATH", "").split(os.pathsep)
|
||||
additions = [str(path) for path in MACOS_EXECUTABLE_DIRECTORIES if path.is_dir()]
|
||||
result["PATH"] = os.pathsep.join(dict.fromkeys([*additions, *existing]))
|
||||
return result
|
||||
|
||||
|
||||
def find_executable(
|
||||
*candidates: str, platform_name: str | None = None
|
||||
) -> str | None:
|
||||
"""Find a command in PATH or in standard macOS package locations."""
|
||||
for candidate in candidates:
|
||||
executable = shutil.which(candidate)
|
||||
if executable:
|
||||
return executable
|
||||
if (platform_name or sys.platform) == "darwin":
|
||||
for directory in MACOS_EXECUTABLE_DIRECTORIES:
|
||||
for candidate in candidates:
|
||||
executable = directory / candidate
|
||||
if executable.is_file() and os.access(executable, os.X_OK):
|
||||
return str(executable)
|
||||
return None
|
||||
|
||||
|
||||
def open_path(path: str | Path) -> None:
|
||||
"""Open a file with the desktop's default application."""
|
||||
target = str(Path(path).expanduser().resolve())
|
||||
@@ -78,17 +114,26 @@ def open_path(path: str | Path) -> None:
|
||||
os.startfile(target) # type: ignore[attr-defined]
|
||||
elif sys.platform.startswith("linux"):
|
||||
subprocess.Popen(["xdg-open", target])
|
||||
elif sys.platform == "darwin":
|
||||
opener = find_executable("open") or "/usr/bin/open"
|
||||
subprocess.Popen([opener, target])
|
||||
else:
|
||||
raise RuntimeError(f"Unsupported platform: {sys.platform}")
|
||||
|
||||
|
||||
def launch_pdf_arranger(path: str | Path) -> None:
|
||||
executable = shutil.which("pdf-arranger") or shutil.which("pdfarranger")
|
||||
if not executable:
|
||||
raise FileNotFoundError(
|
||||
"PDF Arranger is not installed or is not available in PATH."
|
||||
)
|
||||
subprocess.Popen([executable, str(Path(path).expanduser().resolve())])
|
||||
target = str(Path(path).expanduser().resolve())
|
||||
executable = find_executable("pdf-arranger", "pdfarranger")
|
||||
if executable:
|
||||
subprocess.Popen([executable, target])
|
||||
return
|
||||
if sys.platform == "darwin":
|
||||
opener = find_executable("open") or "/usr/bin/open"
|
||||
subprocess.Popen([opener, "-b", "com.apple.Preview", target])
|
||||
return
|
||||
raise FileNotFoundError(
|
||||
"PDF Arranger is not installed or is not available in PATH."
|
||||
)
|
||||
|
||||
|
||||
def replace_with_link_or_copy(
|
||||
@@ -118,4 +163,3 @@ def replace_with_link_or_copy(
|
||||
|
||||
shutil.copy2(source_path, destination_path)
|
||||
return "copy"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user