a90b7443e4
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
108 lines
3.9 KiB
Python
108 lines
3.9 KiB
Python
"""Abre un vault en la app de escritorio Obsidian via el esquema obsidian://.
|
|
|
|
Construye el URI `obsidian://open?vault=<name>` y lanza la app para abrir ese vault.
|
|
Opcionalmente lo registra antes en la config de la app si recibe una ruta existente
|
|
no registrada (compone register_obsidian_vault del grupo obsidian).
|
|
|
|
Funcion impura: puede escribir la config de la app (al registrar) y lanza un proceso
|
|
externo (xdg-open) de forma desacoplada para abrir el URI en Obsidian.
|
|
"""
|
|
|
|
import os
|
|
import subprocess
|
|
import urllib.parse
|
|
|
|
from obsidian import register_obsidian_vault
|
|
|
|
|
|
def open_obsidian_vault(
|
|
vault: str,
|
|
register_if_missing: bool = True,
|
|
launch: bool = True,
|
|
config_path: str = "",
|
|
) -> dict:
|
|
"""Abre un vault en la app Obsidian construyendo y lanzando un URI obsidian://.
|
|
|
|
Args:
|
|
vault: ruta absoluta a un vault o su nombre (basename). Si es una ruta
|
|
existente, el nombre del URI es su basename; si no parece una ruta
|
|
existente se trata como nombre tal cual.
|
|
register_if_missing: si True (default) y vault es una ruta existente no
|
|
registrada en la app, la registra (open=True) antes de abrir.
|
|
launch: si True (default) lanza la app via `xdg-open <uri>` desacoplado.
|
|
Si False (util en tests) NO lanza nada, solo construye el URI.
|
|
config_path: ruta al obsidian.json de la app. Vacio -> default
|
|
~/.config/obsidian/obsidian.json. Se pasa a register_obsidian_vault.
|
|
|
|
Returns:
|
|
dict con:
|
|
- vault: el argumento original recibido.
|
|
- uri: el URI obsidian://open?vault=<name> construido.
|
|
- name: nombre del vault usado en el URI (basename o el propio vault).
|
|
- launched: True si se lanzo xdg-open.
|
|
- registered_now: True si se registro el vault en esta llamada.
|
|
|
|
Raises:
|
|
OSError: si el lanzamiento del proceso o el registro fallan por I/O.
|
|
"""
|
|
registered_now = False
|
|
is_path = os.path.sep in vault or vault.startswith("~")
|
|
abs_path = os.path.abspath(os.path.expanduser(vault)) if is_path else ""
|
|
|
|
# Si es una ruta existente, opcionalmente registrarla y usar su basename.
|
|
if abs_path and os.path.isdir(abs_path):
|
|
name = os.path.basename(abs_path.rstrip(os.path.sep))
|
|
if register_if_missing:
|
|
res = register_obsidian_vault(abs_path, open=True, config_path=config_path)
|
|
registered_now = bool(res.get("registered"))
|
|
elif is_path:
|
|
# Parece ruta pero no existe: usar su basename como nombre.
|
|
name = os.path.basename(abs_path.rstrip(os.path.sep))
|
|
else:
|
|
# Es un nombre, no una ruta.
|
|
name = vault
|
|
|
|
uri = "obsidian://open?vault=" + urllib.parse.quote(name)
|
|
|
|
launched = False
|
|
if launch:
|
|
env = dict(os.environ)
|
|
subprocess.Popen(
|
|
["xdg-open", uri],
|
|
stdin=subprocess.DEVNULL,
|
|
stdout=subprocess.DEVNULL,
|
|
stderr=subprocess.DEVNULL,
|
|
start_new_session=True,
|
|
env=env,
|
|
)
|
|
launched = True
|
|
|
|
return {
|
|
"vault": vault,
|
|
"uri": uri,
|
|
"name": name,
|
|
"launched": launched,
|
|
"registered_now": registered_now,
|
|
}
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import tempfile
|
|
|
|
tmp = tempfile.mkdtemp()
|
|
cfg = os.path.join(tmp, "obsidian.json")
|
|
vault = os.path.join(tmp, "Mi Vault")
|
|
os.makedirs(vault, exist_ok=True)
|
|
|
|
r = open_obsidian_vault(vault, launch=False, config_path=cfg)
|
|
assert r["launched"] is False, r
|
|
assert r["registered_now"] is True, r
|
|
assert r["name"] == "Mi Vault", r
|
|
assert r["uri"] == "obsidian://open?vault=Mi%20Vault", r
|
|
|
|
# Por nombre, sin lanzar ni registrar.
|
|
r2 = open_obsidian_vault("MiVaultPorNombre", launch=False, config_path=cfg)
|
|
assert r2["uri"] == "obsidian://open?vault=MiVaultPorNombre", r2
|
|
assert r2["registered_now"] is False, r2
|
|
print("open_obsidian_vault smoke OK")
|