ring-cli 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ring/__init__.py +12 -0
- ring/__main__.py +6 -0
- ring/cli.py +685 -0
- ring/config.py +276 -0
- ring/focus/__init__.py +65 -0
- ring/focus/applescript.py +34 -0
- ring/focus/base.py +19 -0
- ring/focus/iterm2.py +28 -0
- ring/focus/terminal.py +25 -0
- ring/focus/tmux.py +38 -0
- ring/hook.py +482 -0
- ring/hook_protocol.py +264 -0
- ring/i18n.py +52 -0
- ring/ipc.py +220 -0
- ring/labels.py +50 -0
- ring/locale/en/LC_MESSAGES/ring.mo +0 -0
- ring/locale/en/LC_MESSAGES/ring.po +395 -0
- ring/locale/ring.pot +484 -0
- ring/notify/__init__.py +120 -0
- ring/notify/base.py +37 -0
- ring/notify/command.py +18 -0
- ring/notify/notify_send.py +30 -0
- ring/notify/osascript_notifier.py +32 -0
- ring/notify/terminal_notifier.py +64 -0
- ring/osascript.py +17 -0
- ring/registry.py +851 -0
- ring/sources/__init__.py +94 -0
- ring/sources/base.py +17 -0
- ring/sources/claude_code.py +23 -0
- ring/sources/codex.py +16 -0
- ring/sources/hook_registry.py +16 -0
- ring/tui.py +360 -0
- ring/watcher.py +107 -0
- ring_cli-0.2.0.dist-info/METADATA +334 -0
- ring_cli-0.2.0.dist-info/RECORD +38 -0
- ring_cli-0.2.0.dist-info/WHEEL +4 -0
- ring_cli-0.2.0.dist-info/entry_points.txt +3 -0
- ring_cli-0.2.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""osascript 後端(macOS 純文字,點擊不可聚焦——terminal-notifier 被擋掉時的退路)。"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from ring.config import get_config
|
|
6
|
+
from ring.i18n import gettext as _
|
|
7
|
+
from ring.notify.base import notify_message
|
|
8
|
+
from ring.notify.command import CommandNotifier
|
|
9
|
+
from ring.osascript import osascript
|
|
10
|
+
from ring.registry import Session
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class OsascriptNotifier(CommandNotifier):
|
|
14
|
+
name = "osascript"
|
|
15
|
+
|
|
16
|
+
def supports_click(self) -> bool:
|
|
17
|
+
return False
|
|
18
|
+
|
|
19
|
+
def send(self, sessions: list[Session]) -> None:
|
|
20
|
+
"""用 osascript 逐 session 各發一則純文字通知(fallback,點擊不可聚焦)。"""
|
|
21
|
+
cfg = get_config()
|
|
22
|
+
for s in sessions:
|
|
23
|
+
message = notify_message(s)
|
|
24
|
+
title = _("RiNG · {project} 在等你回話", project=s.project)
|
|
25
|
+
sound = f' sound name "{cfg.notify_sound_name}"' if cfg.notify_sound else ""
|
|
26
|
+
try:
|
|
27
|
+
osascript(f'display notification "{message}" with title "{title}"{sound}')
|
|
28
|
+
except Exception:
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
notifier = OsascriptNotifier()
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""terminal-notifier 後端(macOS,支援點擊 ``ring focus`` 跳轉)。"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import shlex
|
|
6
|
+
import shutil
|
|
7
|
+
import subprocess
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from ring.config import get_config
|
|
12
|
+
from ring.i18n import gettext as _
|
|
13
|
+
from ring.notify.base import notify_message
|
|
14
|
+
from ring.notify.command import CommandNotifier
|
|
15
|
+
from ring.registry import Session
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _ring_executable() -> str:
|
|
19
|
+
"""回傳可被 terminal-notifier click callback 執行的 ring 路徑。
|
|
20
|
+
|
|
21
|
+
macOS 從通知中心觸發 ``-execute`` 時不一定有使用者 shell 的 PATH;通知建立時
|
|
22
|
+
先解析成絕對路徑,點擊才不會因找不到 ``ring`` 而失效。
|
|
23
|
+
"""
|
|
24
|
+
current = Path(sys.argv[0])
|
|
25
|
+
if current.is_absolute() and current.exists():
|
|
26
|
+
return str(current)
|
|
27
|
+
found = shutil.which("ring")
|
|
28
|
+
return found or "ring"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _ring_focus_command(session_id: str) -> str:
|
|
32
|
+
return f"{shlex.quote(_ring_executable())} focus {shlex.quote(session_id)}"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class TerminalNotifierNotifier(CommandNotifier):
|
|
36
|
+
name = "terminal-notifier"
|
|
37
|
+
|
|
38
|
+
def supports_click(self) -> bool:
|
|
39
|
+
return True
|
|
40
|
+
|
|
41
|
+
def send(self, sessions: list[Session]) -> None:
|
|
42
|
+
"""每個 session 各發一則 terminal-notifier 通知,帶點擊聚焦回呼。"""
|
|
43
|
+
cfg = get_config()
|
|
44
|
+
for s in sessions:
|
|
45
|
+
cmd = [
|
|
46
|
+
"terminal-notifier",
|
|
47
|
+
"-title",
|
|
48
|
+
_("RiNG · {project} 在等你回話", project=s.project),
|
|
49
|
+
"-message",
|
|
50
|
+
notify_message(s),
|
|
51
|
+
"-execute",
|
|
52
|
+
_ring_focus_command(s.session_id),
|
|
53
|
+
]
|
|
54
|
+
if cfg.notify_sound:
|
|
55
|
+
cmd.extend(["-sound", cfg.notify_sound_name or "default"])
|
|
56
|
+
if cfg.notify_ignore_dnd:
|
|
57
|
+
cmd.append("-ignoreDnD")
|
|
58
|
+
try:
|
|
59
|
+
subprocess.run(cmd, capture_output=True, timeout=10)
|
|
60
|
+
except Exception:
|
|
61
|
+
pass
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
notifier = TerminalNotifierNotifier()
|
ring/osascript.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""跑一段 AppleScript 的小工具——平台中立的共用 helper。
|
|
2
|
+
|
|
3
|
+
focus(找終端分頁)、notify(osascript 後端)、cli(doctor 探 app 是否在跑)都用它,
|
|
4
|
+
所以放在不綁任何 feature 的中性模組,而不是塞在 ``focus`` 裡讓別人反向依賴 focus。
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import subprocess
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def osascript(script: str) -> tuple[int, str, str]:
|
|
13
|
+
try:
|
|
14
|
+
result = subprocess.run(["osascript", "-e", script], capture_output=True, text=True, timeout=5)
|
|
15
|
+
except (OSError, subprocess.SubprocessError) as exc:
|
|
16
|
+
return 1, "", str(exc)
|
|
17
|
+
return result.returncode, result.stdout.strip(), result.stderr.strip()
|