plexi-sdk 0.4.0__tar.gz

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.
@@ -0,0 +1,61 @@
1
+ # Build
2
+ /target/
3
+ deps/egui_term/target/
4
+
5
+ # Scratch docs
6
+ docs/scratch/
7
+
8
+ # IDE
9
+ .idea/
10
+ .vscode/
11
+
12
+ # AI tool configs (local only)
13
+ .agents/
14
+ .claude/settings.local.json
15
+ .claude/*.lock
16
+ .kiro/
17
+ /skills-lock.json
18
+
19
+ # OS
20
+ .DS_Store
21
+ Thumbs.db
22
+
23
+ # Environment
24
+ .env
25
+ .env.local
26
+
27
+ # Generated bundle assets (cargo bundle generates its own from Cargo.toml)
28
+ assets/Info.plist
29
+
30
+ # Bundled Python runtime (fetched by `just fetch-python-runtime` at build time)
31
+ assets/python/
32
+
33
+ # Channel (per-worktree, not shared)
34
+ .channel
35
+
36
+ # Misc
37
+ *.log
38
+ *.swp
39
+ *.swo
40
+ here.md
41
+ NEXT.md
42
+ examples/*/target/
43
+ sdk/*/target/
44
+ worktrees/
45
+
46
+ # Python
47
+ __pycache__/
48
+ *.pyc
49
+ *.pyo
50
+ sdk/python/**/__pycache__/
51
+ sdk/python/*.egg-info/
52
+
53
+ # Local config
54
+ .plexi/
55
+ .plexi-alpha/
56
+ .plexi-beta/
57
+ .plexi-pr-*/
58
+ .superpowers/
59
+
60
+ # Claude agent memory (local, not shared)
61
+ .claude/agent-memory/
@@ -0,0 +1,127 @@
1
+ Metadata-Version: 2.4
2
+ Name: plexi-sdk
3
+ Version: 0.4.0
4
+ Summary: Python SDK for building Plexi apps via the PGAP v3 protocol
5
+ Project-URL: Homepage, https://github.com/ianjamesburke/PLEXI
6
+ Project-URL: Repository, https://github.com/ianjamesburke/PLEXI
7
+ Project-URL: Documentation, https://github.com/ianjamesburke/PLEXI/tree/main/sdk/python
8
+ Author-email: Ian Burke <ianjamesburke@gmail.com>
9
+ License: MIT
10
+ Keywords: apps,pgap,plexi,sdk,tiling,window-manager
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Software Development :: Libraries
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+
23
+ # plexi-sdk
24
+
25
+ Python SDK for building Plexi apps via the PGAP v3 protocol.
26
+
27
+ Full API reference: `plexi_sdk/__init__.py` docstring.
28
+
29
+ ---
30
+
31
+ ## Keyboard Conventions
32
+
33
+ Apps should follow these standard navigation bindings so users get consistent behavior across all Plexi apps.
34
+
35
+ ### Key name strings
36
+
37
+ Keys arrive in `on_key(ctx, key, mods)` as **lowercase canonical strings**:
38
+
39
+ | Physical key | `key` string |
40
+ |---|---|
41
+ | Enter / Return | `"return"` |
42
+ | Escape | `"escape"` |
43
+ | Backspace | `"backspace"` |
44
+ | Tab | `"tab"` |
45
+ | Space | `"space"` |
46
+ | Arrow keys | `"up"` / `"down"` / `"left"` / `"right"` |
47
+
48
+ The SDK normalizes egui's internal key names automatically. Always match against
49
+ the lowercase canonical strings — `key == "return"`, not `key == "Enter"`.
50
+
51
+ ### Focus / modal conventions
52
+
53
+ | Action | Key |
54
+ |---|---|
55
+ | Open item / confirm / select | `"return"` |
56
+ | Exit focused view / go back | `"escape"` |
57
+ | Exit focused view (fallback) | `"backspace"` (optional second binding) |
58
+
59
+ Any view that opens a focused sub-view (detail panel, modal, inline editor) must
60
+ let the user exit with `"escape"`. No view should be a dead end.
61
+
62
+ **TextInput exception:** `"return"` fires `on_text_submitted`, so the TextInput
63
+ widget owns that key while focused. `"escape"` should still dismiss the
64
+ surrounding view or cancel the input mode.
65
+
66
+ ```python
67
+ def on_key(self, ctx, key, mods):
68
+ if self.detail_open:
69
+ if key in ("escape", "backspace"):
70
+ self.detail_open = False
71
+ return
72
+ if key == "return":
73
+ self._confirm()
74
+ return
75
+ # list navigation below
76
+ ```
77
+
78
+ ### List navigation
79
+
80
+ Standard bindings for any scrollable list:
81
+
82
+ | Key | Action |
83
+ |---|---|
84
+ | `j` / `"down"` | Move selection down |
85
+ | `k` / `"up"` | Move selection up |
86
+ | `"return"` | Open selected item |
87
+ | `"escape"` | Exit list / go back |
88
+
89
+ ---
90
+
91
+ ## List + Detail Views
92
+
93
+ For any app with a list-and-detail pattern, prefer `SelectList` from
94
+ `plexi_sdk.ui` over managing selection state manually. It handles j/k/arrow
95
+ navigation, scroll-to-keep-selected-visible, and click hit-testing.
96
+
97
+ ```python
98
+ from plexi_sdk import App
99
+ from plexi_sdk.ui import SelectList, Column
100
+
101
+ class MyApp(App):
102
+ async def on_init(self, ctx):
103
+ self.items = [{"name": "Alpha"}, {"name": "Beta"}, {"name": "Gamma"}]
104
+ self.list = SelectList(self.items) # stateful — create once, not per frame
105
+ self.detail_open = False
106
+
107
+ def on_key(self, ctx, key, mods):
108
+ if self.detail_open:
109
+ if key in ("escape", "backspace"):
110
+ self.detail_open = False
111
+ return
112
+ if key == "return":
113
+ self.detail_open = True
114
+ return
115
+ self.list.handle_key(key) # handles j/k/up/down
116
+
117
+ def on_render(self, ctx):
118
+ if self.detail_open:
119
+ ctx.text(20, 40, self.items[self.list.selected_idx]["name"])
120
+ else:
121
+ ctx.draw(Column([self.list.render(self.items)]))
122
+ ```
123
+
124
+ `SelectList` is stateful — create it in `on_init`, not `on_render`.
125
+
126
+ For the lower-level `ctx.list_view()` primitive (draw only, no state) see the
127
+ `ListItem` shape in the API reference.
@@ -0,0 +1,105 @@
1
+ # plexi-sdk
2
+
3
+ Python SDK for building Plexi apps via the PGAP v3 protocol.
4
+
5
+ Full API reference: `plexi_sdk/__init__.py` docstring.
6
+
7
+ ---
8
+
9
+ ## Keyboard Conventions
10
+
11
+ Apps should follow these standard navigation bindings so users get consistent behavior across all Plexi apps.
12
+
13
+ ### Key name strings
14
+
15
+ Keys arrive in `on_key(ctx, key, mods)` as **lowercase canonical strings**:
16
+
17
+ | Physical key | `key` string |
18
+ |---|---|
19
+ | Enter / Return | `"return"` |
20
+ | Escape | `"escape"` |
21
+ | Backspace | `"backspace"` |
22
+ | Tab | `"tab"` |
23
+ | Space | `"space"` |
24
+ | Arrow keys | `"up"` / `"down"` / `"left"` / `"right"` |
25
+
26
+ The SDK normalizes egui's internal key names automatically. Always match against
27
+ the lowercase canonical strings — `key == "return"`, not `key == "Enter"`.
28
+
29
+ ### Focus / modal conventions
30
+
31
+ | Action | Key |
32
+ |---|---|
33
+ | Open item / confirm / select | `"return"` |
34
+ | Exit focused view / go back | `"escape"` |
35
+ | Exit focused view (fallback) | `"backspace"` (optional second binding) |
36
+
37
+ Any view that opens a focused sub-view (detail panel, modal, inline editor) must
38
+ let the user exit with `"escape"`. No view should be a dead end.
39
+
40
+ **TextInput exception:** `"return"` fires `on_text_submitted`, so the TextInput
41
+ widget owns that key while focused. `"escape"` should still dismiss the
42
+ surrounding view or cancel the input mode.
43
+
44
+ ```python
45
+ def on_key(self, ctx, key, mods):
46
+ if self.detail_open:
47
+ if key in ("escape", "backspace"):
48
+ self.detail_open = False
49
+ return
50
+ if key == "return":
51
+ self._confirm()
52
+ return
53
+ # list navigation below
54
+ ```
55
+
56
+ ### List navigation
57
+
58
+ Standard bindings for any scrollable list:
59
+
60
+ | Key | Action |
61
+ |---|---|
62
+ | `j` / `"down"` | Move selection down |
63
+ | `k` / `"up"` | Move selection up |
64
+ | `"return"` | Open selected item |
65
+ | `"escape"` | Exit list / go back |
66
+
67
+ ---
68
+
69
+ ## List + Detail Views
70
+
71
+ For any app with a list-and-detail pattern, prefer `SelectList` from
72
+ `plexi_sdk.ui` over managing selection state manually. It handles j/k/arrow
73
+ navigation, scroll-to-keep-selected-visible, and click hit-testing.
74
+
75
+ ```python
76
+ from plexi_sdk import App
77
+ from plexi_sdk.ui import SelectList, Column
78
+
79
+ class MyApp(App):
80
+ async def on_init(self, ctx):
81
+ self.items = [{"name": "Alpha"}, {"name": "Beta"}, {"name": "Gamma"}]
82
+ self.list = SelectList(self.items) # stateful — create once, not per frame
83
+ self.detail_open = False
84
+
85
+ def on_key(self, ctx, key, mods):
86
+ if self.detail_open:
87
+ if key in ("escape", "backspace"):
88
+ self.detail_open = False
89
+ return
90
+ if key == "return":
91
+ self.detail_open = True
92
+ return
93
+ self.list.handle_key(key) # handles j/k/up/down
94
+
95
+ def on_render(self, ctx):
96
+ if self.detail_open:
97
+ ctx.text(20, 40, self.items[self.list.selected_idx]["name"])
98
+ else:
99
+ ctx.draw(Column([self.list.render(self.items)]))
100
+ ```
101
+
102
+ `SelectList` is stateful — create it in `on_init`, not `on_render`.
103
+
104
+ For the lower-level `ctx.list_view()` primitive (draw only, no state) see the
105
+ `ListItem` shape in the API reference.