eolib: Leo's model without a GUI, a terminal front end, and a Rust port

97 views
Skip to first unread message

Shakeeb

unread,
Sep 11, 2026, 5:54:51 AMSep 11
to leo-editor
Hi all,

Recently, with the help of claude code, I had a crack at trying to separate Leo's model from its Qt front end. This led to the [decouple-model-gui](https://github.com/shakfu/leo-editor/tree/decouple-model-gui) branch of my leo fork and the creation of something called `leolib` which includes the model but not the view. It has reached a point where I thought it may be useful to others to look at it if they liked.

`leolib` can open, create, edit and save `.leo` files, including every `@file` kind, with no commander, no frame and no gui:

```python
from leo import leolib
doc = leolib.Document.open('myfile.leo')
child = doc.insert_child(doc.outline.rootPosition())
doc.set_headline(child, 'written with no window in sight')
doc.undo()
doc.save()
```

**Where it stands**

- The model lives in `leo/leolib/` and no longer imports `leoGlobals` or any view module. `leoNodes`, `leoOutline`, `leoFileCommands`, `leoAtFile`, `leoShadow`, `leoImport`, `leoUndo` and friends moved there. The old `leo.core.*` paths are aliases for the new modules (the same module objects, not copies), so no plugin needs to change.

- Opening `LeoPyRef.leo` and reading all its external files imports 13 `leo.*` modules through `leolib`, against about 105 through `leoBridge`. The outlines are identical, node for node.

- A Document class holds an outline and its undo history, and has the structural commands: insert, delete, clone, cut, copy, paste, moves, demote, promote, unmark-all. It records the same undo beads Leo's own commands do.

- `leo/leotui` is a small terminal front end written against `leolib` alone. What a front end has to supply is about ten members, listed in `leolib`'s `HeadlessView`.

- 999 tests pass, and ruff, ty and `check_leo_sync` are clean. Qt Leo runs as before; single-window editing and saving are confirmed by hand.

**A Rust port, and a shared test corpus**

As a proof-of-concept, I ported `leolib` -- again with the help of claude code -- to rust. This became [leo-rs](https://github.com/shakfu/leo-rs) which includes two crates: the rust `leolib` port and `leotui`, a terminal front end (vim-style editing, tree-sitter highlighting). It reads `LeoPyRef.leo` and its external files identically to the Python `leolib`, rewrites the `.leo` file byte for byte, and tangles the external files it has checked back to the bytes on disk.

As things happens, the rust port has evolved into a workable vim-like editor.

The two implementations now share a conformance 'corpus' test: a bunch of outlines covering every `@<file>` kind, clones, CRLF, latin-1, lines that look like sentinels, and `@auto` in four languages.

**Discovery of leo-cub**

After developing the rust port to some extent, I ran a 'rust leo' search in the leo-editor group and found the cool [leo-cub](https://github.com/vivainio/leo-cub) project that Ville Vainio is developing (also in rust).

I haven't really compared features, but it looks like `leo-cub` is lot more mature and is likely more compatible with leo with  more features than the rust leotui implementation but the latter has some nice 'editor' features like vim-like modal editing / search and tree-sitter-based helix-style themes for syntax highlighting.

**Hope this is useful**

I would be pleased if any of the code which came out of this experiment proved useful for the leo-editor project or to other related projects.

S

jkn

unread,
Sep 11, 2026, 2:47:08 PMSep 11
to leo-editor
Not to denigrate any of your efforts here, but my understanding what that Leo has separated the GUI code from the 'Model' for many years now. The Qt 'view' is not the only one there has ever been ... until relatively recently you could also use ttk, and IIRC Edward (and others) have experimented with Flexx, text-only, and probably others.

I am curious what extra, or different, separation you might have done here

    Regards
    J^n

Edward K. Ream

unread,
Sep 11, 2026, 3:27:38 PMSep 11
to leo-editor
On Friday, September 11, 2026 at 4:54:51 AM UTC-5 Shakeeb wrote:

Recently, with the help of claude code, I had a crack at trying to separate Leo's model from its Qt front end.

Leo's model is already separate from its gui. I can explain more if you like, but first I would suggest looking (without faux help) at Leo's sources. Feel free to ask any questions you like.

Edward

Shakeeb

unread,
Sep 11, 2026, 3:54:28 PMSep 11
to leo-editor
Thanks for your reply.

You're right to push back. My earlier claim of decoupling the model from the view was overstated. Leo has separated its GUI toolkits for a long time. What it has not separated is the document from the window: every front end still runs a commander that builds a frame.

My aim narrowed to this: extract the outline model so it runs without an app, a GUI or a commander, plus the minimum needed to drive a terminal view.

What differs from upstream so far:

- An `Outline` object owns the tree, files and undo. `Commands` keeps the view state, and `VNode.context` is now the `Outline`.

- `leolib` can open, edit, save and tangle a `.leo` file without a commander. Reading `LeoPyRef.leo` loads 13 modules, versus 105 through `leoBridge`, with identical results.

- The model, not the widget, holds node text, and it emits change events that views can follow.

It is not self-contained yet. The `leolib` code spans three directories (`leo/leolib`, `leo/core`, `leo/plugins`). Several core modules still mix model and view code, and an `@auto` node still loads `leoGlobals`. Most of my time since has gone into a Rust reimplementation of the model, in a separate repository, so the Python side has not moved much.

Regards,

S

Shakeeb

unread,
Sep 11, 2026, 4:01:02 PMSep 11
to leo-editor
Hi Ed,
 
Leo's model is already separate from its gui. I can explain more if you like, but first I would suggest looking (without faux help) at Leo's sources. Feel free to ask any questions you like.

Thanks for clarification and advice. I overstated the part about separation, when my focus was more about extracting the minimal outline model.

Regards,

S
 

Ville M. Vainio

unread,
Sep 12, 2026, 8:10:11 AMSep 12
to leo-e...@googlegroups.com
On leo-cub - 

Yes, I have intentionally outscoped rich body editor. Currently I just use helix as my $EDITOR and launch that when I edit the body. There is a very minimal editor where you can copy paste stuff quickly but that's pretty much it.

I rarely edit raw text nowadays as I do ~ everything with AI, and also don't want to be in business of creating an editor (people are quite set in their ways on what editor they want to use)

Cub supports the leo @auto, @edit etc and then some (e.g. see @auto-dir here https://vivainio.github.io/leo-cub/reference/files-and-paths/)

You may want to clone the repo and check code reuse opportunities. Also try it out (uv tool install leo-cub), it's pretty snazzy if I say so myself ;-). I use it regularly. There is also leo-like scripting API with Rhai: https://vivainio.github.io/leo-cub/reference/rhai-api


--
You received this message because you are subscribed to the Google Groups "leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email to leo-editor+...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/leo-editor/0172a6d3-ba4f-480b-be66-3591065f8a9cn%40googlegroups.com.

Ville M. Vainio

unread,
Sep 12, 2026, 8:11:24 AMSep 12
to leo-e...@googlegroups.com
Eh sorry, this is probably better entry point to Cub scripting: https://vivainio.github.io/leo-cub/workflows/scripting/

Shakeeb

unread,
Sep 15, 2026, 2:20:46 PMSep 15
to leo-editor
Thanks Ville.  I'll check it out. There are definitely opportunities for code re-use. Thanks!

Also when you have a chance, check out leotui: https://crates.io/crates/leotui 

I will be working on compatibility and also maybe borrow incorporate some ideas from leo-cub --- rhai sounds cool!

S

Edward K. Ream

unread,
Sep 16, 2026, 7:25:46 AMSep 16
to leo-e...@googlegroups.com
On Tue, Sep 15, 2026 at 1:20 PM Shakeeb <shakeeb...@gmail.com> wrote:
Thanks Ville.  I'll check it out. There are definitely opportunities for code re-use. Thanks!

Also when you have a chance, check out leotui: https://crates.io/crates/leotui 

I will be working on compatibility and also maybe borrow incorporate some ideas from leo-cub --- rhai sounds cool!

Excellent. I'm glad you didn't let me discourage you.

Edward
Reply all
Reply to author
Forward
0 new messages