leo-cub 0.2.2__py3-none-android_24_arm64_v8a.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.
|
Binary file
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: leo-cub
|
|
3
|
+
Version: 0.2.2
|
|
4
|
+
Classifier: Development Status :: 3 - Alpha
|
|
5
|
+
Classifier: Environment :: Console
|
|
6
|
+
Classifier: Intended Audience :: Developers
|
|
7
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Programming Language :: Rust
|
|
11
|
+
Classifier: Topic :: Text Editors
|
|
12
|
+
Classifier: Topic :: Utilities
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Summary: Automation-safe library and CLI for Leo outline files
|
|
15
|
+
Keywords: leo-editor,outline,cli,tui,automation
|
|
16
|
+
Author-email: Ville Vainio <vivainio@gmail.com>
|
|
17
|
+
License: MIT OR Apache-2.0
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
20
|
+
Project-URL: Homepage, https://github.com/vivainio/leo-cub
|
|
21
|
+
Project-URL: Repository, https://github.com/vivainio/leo-cub
|
|
22
|
+
|
|
23
|
+
# leo-cub
|
|
24
|
+
|
|
25
|
+
`leo-cub` is an experimental Rust library and command-line tool for reading,
|
|
26
|
+
validating, browsing, and modifying [Leo Editor](https://leo-editor.github.io/leo-editor/)
|
|
27
|
+
outlines.
|
|
28
|
+
|
|
29
|
+
The installed command is `cub`; the Rust library namespace is `leo`.
|
|
30
|
+
|
|
31
|
+
## Screenshot
|
|
32
|
+
|
|
33
|
+
<img width="1836" height="933" alt="image" src="https://github.com/user-attachments/assets/2ff24163-62a2-487b-aaf5-a9ec8c2beb73" />
|
|
34
|
+
|
|
35
|
+
## Why
|
|
36
|
+
|
|
37
|
+
Leo outlines are not ordinary XML trees. A GNX identifies shared vnode content,
|
|
38
|
+
while an outline position identifies one occurrence of that vnode. Cloned nodes
|
|
39
|
+
can therefore appear in several places. `leo-cub` keeps those concepts separate
|
|
40
|
+
and exposes transactional operations intended for scripts and AI tools.
|
|
41
|
+
|
|
42
|
+
## Current features
|
|
43
|
+
|
|
44
|
+
- Parse and validate `.leo` XML outlines.
|
|
45
|
+
- Preserve XML outside the rewritten `<vnodes>` and `<tnodes>` sections.
|
|
46
|
+
- Represent clone identity separately from outline positions.
|
|
47
|
+
- Apply atomic JSON operation batches with optional text preconditions.
|
|
48
|
+
- Parse Leo 5 thin derived-file sentinels.
|
|
49
|
+
- Reconstruct `@file`, `@thin`, and `@file-thin` hierarchies and bodies.
|
|
50
|
+
- Resolve ancestor `@path` directives in the TUI.
|
|
51
|
+
- Browse outlines with a small Ratatui interface.
|
|
52
|
+
- Highlight node bodies with Syntect, using `@language`, `@rst` ancestors, or
|
|
53
|
+
source extensions, including bundled reStructuredText syntax support.
|
|
54
|
+
- Open a derived node's full source file at its sentinel line using `$VISUAL` or
|
|
55
|
+
`$EDITOR`.
|
|
56
|
+
|
|
57
|
+
## Install
|
|
58
|
+
|
|
59
|
+
The recommended installation method is [`uv`](https://docs.astral.sh/uv/):
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
uv tool install leo-cub
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
This installs the `cub` command. You can also use `pip install leo-cub`,
|
|
66
|
+
or download the appropriate archive
|
|
67
|
+
from the [latest GitHub release](https://github.com/vivainio/leo-cub/releases/latest).
|
|
68
|
+
|
|
69
|
+
### Termux
|
|
70
|
+
|
|
71
|
+
The PyPI release includes an Android API 24 ARM64 wheel suitable for current
|
|
72
|
+
64-bit Termux installations:
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
uv tool install leo-cub
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
To build the command locally in Termux instead, install the native toolchain
|
|
79
|
+
and build from a repository checkout:
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
pkg install rust clang git
|
|
83
|
+
git clone https://github.com/vivainio/leo-cub.git
|
|
84
|
+
cd leo-cub
|
|
85
|
+
cargo install --path . --locked
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Installation from source
|
|
89
|
+
|
|
90
|
+
From the repository root, install the `cub` command with Cargo:
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
cargo install --path .
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Install the bundled local agent skill after installing the command:
|
|
97
|
+
|
|
98
|
+
```sh
|
|
99
|
+
cub install-skills
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
This writes `~/.claude/skills/leo-cub/SKILL.md` and overwrites an existing
|
|
103
|
+
copy, so it is safe to rerun after upgrading.
|
|
104
|
+
|
|
105
|
+
## TUI
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
cub tui outline.leo
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The browser resolves external thin files in memory. Outline headlines highlight
|
|
112
|
+
Leo directives, external-file names, and section-reference markers. A red `*`
|
|
113
|
+
marks each node changed since the outline was loaded or last saved; saving or
|
|
114
|
+
reloading clears the markers.
|
|
115
|
+
|
|
116
|
+
## TUI keybindings
|
|
117
|
+
|
|
118
|
+
### Browsing and display
|
|
119
|
+
|
|
120
|
+
| Key | Action |
|
|
121
|
+
| --- | --- |
|
|
122
|
+
| `↓` / `↑` | Select next/previous node |
|
|
123
|
+
| `→`, `Enter` | Expand selected node |
|
|
124
|
+
| `←` | Collapse selected node |
|
|
125
|
+
| `Home` / `End` | Select the first/last visible node |
|
|
126
|
+
| `PageUp` / `PageDown` | Scroll the selected node's body by one page |
|
|
127
|
+
| `f` | Toggle a full-width body pane |
|
|
128
|
+
| `Shift-F` | Toggle a full-width outline pane |
|
|
129
|
+
| `↑` / `↓` in full-width mode | Scroll the body vertically by one line |
|
|
130
|
+
| `←` / `→` in full-width mode | Scroll the body horizontally |
|
|
131
|
+
| `Ctrl-P` | Find a headline incrementally; use `↑`/`↓` to cycle matches |
|
|
132
|
+
| `o` | Edit the node body in `$VISUAL`/`$EDITOR`; for derived nodes, open the real source at its sentinel |
|
|
133
|
+
| `y` | Toggle syntax highlighting |
|
|
134
|
+
| `?` | Show command help |
|
|
135
|
+
|
|
136
|
+
### Outline editing
|
|
137
|
+
|
|
138
|
+
| Key | Action |
|
|
139
|
+
| --- | --- |
|
|
140
|
+
| `Ctrl-I` or `Tab` | Insert a new sibling and enter headline editing |
|
|
141
|
+
| `Ctrl-H` or `Backspace` | Edit the selected headline |
|
|
142
|
+
| `Ctrl-↑`, `Ctrl-↓` | Move among siblings |
|
|
143
|
+
| `Ctrl-←`, `Ctrl-→` | Promote or demote the selected node |
|
|
144
|
+
| `Ctrl-R` | Reload from disk; press twice to discard unsaved changes |
|
|
145
|
+
| `Ctrl-S` | Save outline changes |
|
|
146
|
+
| `q` or `Esc` | Quit; press twice to discard unsaved changes |
|
|
147
|
+
|
|
148
|
+
### Headline editing
|
|
149
|
+
|
|
150
|
+
| Key | Action |
|
|
151
|
+
| --- | --- |
|
|
152
|
+
| Printable characters | Append to the headline |
|
|
153
|
+
| `Backspace` | Delete the previous character |
|
|
154
|
+
| `Enter` | Accept the headline |
|
|
155
|
+
| `Esc` | Cancel editing; a newly inserted node is removed |
|
|
156
|
+
|
|
157
|
+
Use `--no-derived` to display only the hierarchy physically present in the
|
|
158
|
+
`.leo` XML file.
|
|
159
|
+
|
|
160
|
+
For source navigation, `cub` recognizes common position arguments for Vim,
|
|
161
|
+
Neovim, Nano, Emacs, VS Code, Microsoft Edit, Helix, and Kakoune. Other editors
|
|
162
|
+
receive the file path without a line argument.
|
|
163
|
+
|
|
164
|
+
## Demo flow
|
|
165
|
+
|
|
166
|
+
Starting in a project containing `README.md` and a `src/` directory, create a
|
|
167
|
+
new outline with destinations for source code, documentation, and tasks:
|
|
168
|
+
|
|
169
|
+
```sh
|
|
170
|
+
cub new project.leo --headline "Project"
|
|
171
|
+
cub add project.leo \
|
|
172
|
+
"Project/Source" \
|
|
173
|
+
"Project/Documentation" \
|
|
174
|
+
"Project/Tasks/Backlog"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Import the source tree below `Project/Source`, preserving its directory
|
|
178
|
+
structure, then import the README as an editable node below the documentation
|
|
179
|
+
branch:
|
|
180
|
+
|
|
181
|
+
```sh
|
|
182
|
+
cub import project.leo src \
|
|
183
|
+
--recursive --mode auto --paths \
|
|
184
|
+
--parent "Project/Source"
|
|
185
|
+
cub import project.leo README.md \
|
|
186
|
+
--mode edit \
|
|
187
|
+
--parent "Project/Documentation"
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Finally, inspect the resulting tree and validate the file:
|
|
191
|
+
|
|
192
|
+
```sh
|
|
193
|
+
cub inspect project.leo
|
|
194
|
+
cub validate project.leo
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
`@auto` source nodes are reconstructed from their files when inspected or
|
|
198
|
+
opened, while the `@edit` README node stores its text in the outline.
|
|
199
|
+
|
|
200
|
+
## Headless commands
|
|
201
|
+
|
|
202
|
+
```sh
|
|
203
|
+
cub new outline.leo
|
|
204
|
+
cub new notes.leo --headline "Notes"
|
|
205
|
+
cub add outline.leo "Project/Tasks/First task" "Project/Notes"
|
|
206
|
+
cub inspect outline.leo
|
|
207
|
+
cub inspect outline.leo src/main.rs
|
|
208
|
+
cub inspect outline.leo --gnx ekr.20260811210000.1
|
|
209
|
+
cub inspect outline.leo --position 0/2/1
|
|
210
|
+
cub inspect outline.leo --search 'render_(compact|json)'
|
|
211
|
+
cub inspect outline.leo --search TODO --search FIXME
|
|
212
|
+
cub inspect outline.leo src/main.rs --format json
|
|
213
|
+
cub validate outline.leo
|
|
214
|
+
cub import outline.leo src --recursive --mode auto --paths
|
|
215
|
+
cub import outline.leo README.md --mode edit --no-paths
|
|
216
|
+
cub import outline.leo README.md --parent "Project/Notes"
|
|
217
|
+
cub sync outline.leo
|
|
218
|
+
cub sync outline.leo src/main.rs --dry-run
|
|
219
|
+
cub sync outline.leo --gnx ekr.20260811210000.1
|
|
220
|
+
cub diff before.leo after.leo
|
|
221
|
+
cub inspect-derived path/to/derived.py --summary
|
|
222
|
+
cub apply outline.leo operations.json --dry-run
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
`new` creates a valid outline with one empty root node. It refuses to overwrite
|
|
226
|
+
an existing file.
|
|
227
|
+
|
|
228
|
+
`add` creates nodes from slash-separated headline paths and reuses shared or
|
|
229
|
+
existing prefixes. `import --parent` accepts either an exact GNX or a unique
|
|
230
|
+
slash-separated headline path. Paths with duplicate matching siblings are
|
|
231
|
+
rejected as ambiguous.
|
|
232
|
+
|
|
233
|
+
`import` creates Leo external-file nodes in `auto`, `edit`, or `clean` mode.
|
|
234
|
+
Markdown, Python, Rust, C#, Go, JavaScript/JSX, and TypeScript/TSX `@auto` files
|
|
235
|
+
are expanded transiently with Tree-sitter when they are loaded by `inspect` or
|
|
236
|
+
the TUI; the generated tree is not stored in the `.leo` file. Unsupported
|
|
237
|
+
source types remain available as a plain root node. Markdown also supports
|
|
238
|
+
Leo's `@auto-md` and `@auto-markdown` headlines and `leo-noheader` markers.
|
|
239
|
+
Directory imports are recursive only with `--recursive` and preserve their
|
|
240
|
+
layout with `@path` nodes by default. Use `--no-paths` to put all imported
|
|
241
|
+
files directly below the destination, `--parent GNX_OR_PATH` to choose that
|
|
242
|
+
destination, and `--dry-run` to validate without saving.
|
|
243
|
+
|
|
244
|
+
`inspect` uses a compact text format containing position paths, GNXs,
|
|
245
|
+
headlines, and bodies. Repeated clone content is shown as `=GNX`. Use
|
|
246
|
+
`--format json` for structured output in scripts.
|
|
247
|
+
`--search` accepts a Rust regular expression and searches headlines and body
|
|
248
|
+
lines. Search results include line-numbered excerpts with two surrounding lines
|
|
249
|
+
instead of printing entire matching bodies. Repeat `--search` to match any of
|
|
250
|
+
several expressions. Thin external files are scanned first and reconstructed
|
|
251
|
+
only when they may contain a search or GNX match.
|
|
252
|
+
|
|
253
|
+
An operation batch is a JSON object:
|
|
254
|
+
|
|
255
|
+
```json
|
|
256
|
+
{
|
|
257
|
+
"operations": [
|
|
258
|
+
{
|
|
259
|
+
"op": "set-body",
|
|
260
|
+
"node": "ekr.20260811210000.1",
|
|
261
|
+
"expected": "old body",
|
|
262
|
+
"body": "new body"
|
|
263
|
+
}
|
|
264
|
+
]
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Operations are applied to a copy and committed only if the complete batch is
|
|
269
|
+
valid. `expected` provides optimistic conflict detection for headline and body
|
|
270
|
+
edits.
|
|
271
|
+
|
|
272
|
+
## Status and safety
|
|
273
|
+
|
|
274
|
+
This project is early and the file format support is incomplete. In particular,
|
|
275
|
+
it does not yet write thin derived files, dynamically interpret every
|
|
276
|
+
`@comment`/`@delims` change, or fully reconstruct all doc-part forms. Keep
|
|
277
|
+
backups and use `--dry-run` when testing write operations on important outlines.
|
|
278
|
+
|
|
279
|
+
The TUI overlays derived files without modifying either the outline or external
|
|
280
|
+
source files. Derived descendants are read-only in the outline editor; use `o`
|
|
281
|
+
to edit their full external source. Unsaved outline changes require a second
|
|
282
|
+
`q` before they are discarded.
|
|
283
|
+
|
|
284
|
+
## License
|
|
285
|
+
|
|
286
|
+
MIT
|
|
287
|
+
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
leo_cub-0.2.2.data/scripts/cub,sha256=0B1HW60JYaWwOskbYRkilT7N6INEsrcdo784BZ7UOfE,17934128
|
|
2
|
+
leo_cub-0.2.2.dist-info/METADATA,sha256=lInYb9YGftHY0iFhwPV75anAUB_rLBBx8nvfD937LMc,9992
|
|
3
|
+
leo_cub-0.2.2.dist-info/WHEEL,sha256=mn8r6A7jQYp8ptC62xilywuPcIEjJSEpm0-18mz1xgg,105
|
|
4
|
+
leo_cub-0.2.2.dist-info/licenses/LICENSE,sha256=gxplErQm68UiJ1LA1RKjUOQKq0dR1Mt5PCn1lsKoCY0,1077
|
|
5
|
+
leo_cub-0.2.2.dist-info/sboms/leo-cub.cyclonedx.json,sha256=nn3jZv_7Ucat331aoa3pUvlk34mzxRr0ppsmkisEJ1E,240720
|
|
6
|
+
leo_cub-0.2.2.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 leo-cub contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|