bearcli 1.0.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.
bearcli/__init__.py ADDED
File without changes
bearcli/actions.py ADDED
@@ -0,0 +1,71 @@
1
+ """Write actions via Bear's x-callback-url scheme.
2
+
3
+ The database stays strictly read-only; all mutations go through Bear's own
4
+ URL API (which launches the app if needed). Calls are fire-and-forget — Bear
5
+ gives no result back — so callers verify outcomes by re-reading the database.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import subprocess
11
+ import time
12
+ from collections.abc import Callable
13
+ from urllib.parse import quote, urlencode
14
+
15
+ BASE_URL = "bear://x-callback-url/"
16
+
17
+
18
+ def call_bear(action: str, foreground: bool = False, **params: str | None) -> None:
19
+ query = urlencode({k: v for k, v in params.items() if v is not None}, quote_via=quote)
20
+ # -g keeps Bear in the background instead of stealing focus.
21
+ cmd = ["open", f"{BASE_URL}{action}?{query}"] if foreground else ["open", "-g", f"{BASE_URL}{action}?{query}"]
22
+ subprocess.run(cmd, check=True)
23
+
24
+
25
+ def create_note(title: str, text: str | None = None, tags: list[str] | None = None) -> None:
26
+ call_bear(
27
+ "create",
28
+ title=title,
29
+ text=text,
30
+ tags=",".join(tags) if tags else None,
31
+ open_note="no",
32
+ show_window="no",
33
+ )
34
+
35
+
36
+ def add_text(note_id: str, text: str, mode: str = "append") -> None:
37
+ call_bear("add-text", id=note_id, text=text, mode=mode, open_note="no", show_window="no")
38
+
39
+
40
+ def add_file(note_id: str, filename: str, file_b64: str) -> None:
41
+ call_bear("add-file", id=note_id, filename=filename, file=file_b64, mode="append", open_note="no", show_window="no")
42
+
43
+
44
+ def rename_tag(name: str, new_name: str) -> None:
45
+ call_bear("rename-tag", name=name, new_name=new_name, show_window="no")
46
+
47
+
48
+ def delete_tag(name: str) -> None:
49
+ call_bear("delete-tag", name=name, show_window="no")
50
+
51
+
52
+ def open_note(note_id: str, new_window: bool = False) -> None:
53
+ call_bear("open-note", foreground=True, id=note_id, new_window="yes" if new_window else "no")
54
+
55
+
56
+ def trash_note(note_id: str) -> None:
57
+ call_bear("trash", id=note_id, show_window="no")
58
+
59
+
60
+ def archive_note(note_id: str) -> None:
61
+ call_bear("archive", id=note_id, show_window="no")
62
+
63
+
64
+ def wait_for(predicate: Callable[[], bool], timeout: float = 6.0, interval: float = 0.3) -> bool:
65
+ """Poll until predicate() is true; Bear applies URL actions asynchronously."""
66
+ deadline = time.monotonic() + timeout
67
+ while time.monotonic() < deadline:
68
+ if predicate():
69
+ return True
70
+ time.sleep(interval)
71
+ return predicate()