Add the outline and Note views, splits, popups and the bars

The outline shows the tree as an indented list: a row per node with its
fold marker, tree lines in the parent's color, tags, a ¶ for a body and
+N for what a fold hides. zb shows every body under its title, to read a
document like a page. j/k go row by row, h/l to the parent and the first
child, a click on a marker folds, and titles are edited in their row,
rapid entry included. In move mode, j/k swap the node with its siblings,
h takes it out a level and l puts it under the one above.

The Note view shows one node at full size, as parts: the title, the
tags, the body, each link and each child. j/k step through them, Enter
or i edits the part (or goes to that link or child), and h/l turn the
page to the sibling before or after. Bodies and tags are edited with the
same editor as titles: Enter starts a line in a body, Tab types spaces,
and tags that don't parse come back as they were. cc, C and s now start
typing on an empty line too, as in vim.

Panes split the screen the way vim's windows do (Ctrl-w v s h j k l w c
o =, :split, :vsplit, :only), each in a box with its view and document,
and any pane can show any open document (gt, gT, :b, the documents
picker, a click on the document bar). The status bar has two lines: the
mode, the view, the breadcrumb or a message, the keys typed; then key
hints for what you're doing, which <Space>w hides with which-key.

Popups are a mode of their own, built on one list: ? lists every key and
command, / searches it and Enter runs what you pick; the right-click menu
lists what you can do with a node (with the keys that do the same) or
adds a new idea on the empty canvas; the pickers set a node's color,
border, style or tags. K opens the body in a card beside the node, where
i edits it in place.

The example now opens two documents (the garden, and the kitchen its
portal leads to) and its tests drive all of the above end to end.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
skkeyeandClaude Opus 5.5 committed 2026-10-01 19:10:09 -04:00
1 parent 84aefbecdb
commit c587c42115
37 files changed
+5579 -730

No files matched your search

+91 -17
View File
@@ -136,8 +136,56 @@ lines.
double-click on a title starts editing at that letter.
- A portal's title is its document's name, so it isn't edited in place: rename
that document instead.
- The editor handles bodies (several lines) too, but they're edited in the Note
view, in stage 7.
- Bodies are edited in the Note view and in the `K` card, with the same
editor: Enter starts a new line, Tab types four spaces. `cc`, `C` and `s`
start typing on an empty line too, as in vim (bodies are often empty).
**Views, panes and popups** (settled in stage 7)
- The Note view is made of parts: the title, the tags, the body, each link
(out, then in) and each child. `j` and `k` step through them, with a bar
marking the one you're on; Enter, `i` or `A` edits it (`I` from its start,
`cc` `S` anew), or goes to that link (a jump: `''` comes back) or child.
`h` and `l` turn the page: the sibling before or after. Node keys (`dd`,
`za`, `o`…) act on the note's node. The note follows the cursor, starting
at the title of each node it comes to.
- The outline has a row per node: its fold marker (`▾` `▸`), tree lines in
the parent's color (as branches are on the canvas), its tags, `¶` when it
has a body, `+N` for what a fold hides. `zb` shows every body under its
title, where its children hang, to read the document like a page. `j` and
`k` go row by row, `h` and `l` to the parent and the first child; a click
on a marker folds. Titles are edited in their row, rapid entry included.
- Move mode in the outline and the Note view moves the node through the
tree: `j` and `k` swap it with its siblings (`J` and `K` five places), `h`
takes it out a level, `l` puts it under the one above.
- The status bar has two lines: the mode, the view, the breadcrumb (or a
message in its place) and the keys typed so far; then the key hints for
what you're doing. `<Space>w` hides the hint line along with which-key.
- Help (`?`, `<Space>?`, `:help [topic]`) lists every key of the focused view
and every `:` command, under which-key's headings. `/` searches (rows that
start with what's typed first, then fuzzy matches), and Enter runs the row:
a key that waits for more (`m`) is typed for you to finish, and a `:`
command that needs an argument opens the command line with it typed.
- The `K` card opens beside the node (in the middle when the node isn't on
screen). `j` `k` `Ctrl-d` `Ctrl-u` scroll it; `i`, `A` or Enter edits the
body right there (`I` from its start), and when that's done the card stays;
`K`, `q` or Esc closes it.
- Right-click opens a menu of what you can do with the node, each with the
keys that do the same; on the empty canvas: a new idea right there (a loose
node), zoom in and out. `<Space>c` `<Space>B` `<Space>s` `<Space>t` open
the color, border, style and tags pickers, which start on what the node has
now. In the tags picker Enter puts a tag on or off and the picker stays
open; a search that matches no tag, then Enter, adds it as a new one.
- Every pane has a box with its view and document in the top border, the
focused one in the accent color. A new pane comes first (left or above)
and takes the focus, as in vim, and closing the last pane quits (`q`,
`ZZ`, `:q`). A click focuses the pane under it; a text edited in the old
one is done first.
- The document bar is always at the top, the focused pane's document
standing out; a click on a name shows that document in the pane. Each pane
can show any open document.
- Popups (the help, the menu, the pickers, the card) are a mode of their own:
keys and clicks go to them, a click outside a list closes it, and they stay
above the status bar.
**Files and saving**
- Documents are RON files ending in `.cum`. Configs are TOML: `config.toml`,
@@ -255,12 +303,13 @@ backlinks, and the backlink paths in every document it points to.
| **Note** | Writing: one node's title, tags, color and body (with vim motions inside), plus its links in and out and its children. It follows the cursor. |
| **Board** (v1.1) | Sorting: columns by tag or color. Moving a card to another column changes its tag. |
- **Pickers:** Documents in v1, Search in v1.1.
- **Pickers:** documents, colors, borders, styles and tags in v1; Search in v1.1.
- **Popups:** which-key (bottom right, as in skyshift), `?` help, the `K` card,
the right-click menu, confirmations, and the command line with its
completion list.
- **Top bar:** the open documents. **Bottom bar:** the mode, the view, the
breadcrumb (or a message), and the keys typed so far (`2g` above).
breadcrumb (or a message), and the keys typed so far (`2g` above); then a
line of key hints, which `<Space>w` hides.
**Mouse** (on the canvas; other views get click, double-click and scroll):
click selects, double-click edits the title (from the letter clicked),
@@ -281,6 +330,8 @@ enum Mode {
Move(Grab), // a node or a branch being moved
Connect(Connect), // the source node and the link being styled
Command(CommandLine), // `:` with completion
Popup(Popup), // the help, the menu, a picker or the K card (which
// holds its own TextEdit while the body is edited)
}
```
@@ -297,7 +348,11 @@ text).
| **Operators** | `dd` or `dab` delete branch · `dib` delete children · `x` delete just the node · `yy` `yab` `yib` yank · `p` `P` paste after / before · `]p` paste as child · `>>` `<<` indent / outdent · `"a`–`"z` and `"+` registers · `.` repeat · `u` `Ctrl-r` undo / redo |
| **Modes** | `v` `V` visual · `M` move · `C` connect · `:` command · Esc back to normal |
| **Leader** `<Space>` | `c` color · `s` style · `B` border · `t` tags · `p` new portal · `i` inbox · `b` documents · `v` then `c`/`o`/`n` for canvas / outline / note · `w` which-key on/off · `?` help |
| **Panes, documents** | `Ctrl-w v` `Ctrl-w s` split · `Ctrl-w hjkl` focus · `Ctrl-w c` close · `Ctrl-w o` only · `Ctrl-w =` even sizes · `gt` `gT` `]b` `[b` next / previous document · `ZZ` close pane |
| **Panes, documents** | `Ctrl-w v` `Ctrl-w s` split · `Ctrl-w hjkl` focus · `Ctrl-w w` the next pane · `Ctrl-w c` close · `Ctrl-w o` only · `Ctrl-w =` even sizes · `gt` `gT` `]b` `[b` next / previous document · `ZZ` close pane (the last one quits) |
| **Outline** | `j` `k` rows · `h` `l` parent / first child · `zb` every body · `M` then `j` `k` (`J` `K`: 5) swap with siblings, `h` out, `l` under the one above |
| **Note view** | `j` `k` parts · Enter `i` `A` edit the part (`I` from its start, `cc` `S` anew), or go to that link or child · `h` `l` the sibling before / after |
| **Lists** (help, menu, pickers) | `j` `k` `gg` `G` `Ctrl-d` `Ctrl-u` move · `/` search · Enter pick or run · Esc or `q` close |
| **K card** | `j` `k` `Ctrl-d` `Ctrl-u` scroll · `i` `A` Enter edit the body (`I` from its start) · `K` `q` Esc close |
| **Typing** | `Backspace` `Delete` · `Ctrl-w` delete word · `Ctrl-u` delete line · arrows, Home, End · Enter (title: done, or after `o O a` the next idea; body: new line) · Tab Shift-Tab (a new idea: under the one above / out a level) · Esc to vim keys |
| **Inside text** | `h j k l w b e 0 ^ $ gg G` (and arrows, Home, End) · `f t F T ; ,` · `d` `c` `y` with any motion and `iw aw i" a" i( a(` · `x X s S D C Y` · `r ~ J p P` · `u Ctrl-r .` · `i a I A` back to typing · `o O` (title: a new sibling; body: a new line) · Esc done |
| **Move mode** | `hjkl` 1 cell · `HJKL` 5 cells · `M` branch ↔ node · Enter or Esc done |
@@ -377,7 +432,7 @@ glyphs = "unicode" # "ascii" for fonts without box-drawing characters
completion_popup = "as-you-type" # "on-tab": only after Tab, like vim's wildmenu
# keys.toml: sections motions, normal, canvas, outline, note, visual, move,
# connect, list, text (vim keys inside text), insert (typing: one key each,
# connect, list, card, text (vim keys inside text), insert (typing: one key each,
# the others type themselves); commands by name (src/input/command.rs);
# "nothing" unbinds
leader = "<Space>"
@@ -437,16 +492,18 @@ cumulus/
│ keymap (+ keys.toml), engine (counts, registers, operators), mouse
├─ command/ registry, parse, complete, history
├─ view/ mod.rs (the View trait), canvas/ (camera, boxes, lines, route, scene, render,
│ navigate, placement, view), outline, note, board
│ navigate, placement, view), outline, note; later board
├─ ui/ text_input (a line of text and its cursor), text_editor/ (vim inside text:
│ motion, object, layout), which_key, command_line, theme, glyphs; later
│ status_bar, document_bar, card, menu, picker, help
│ motion, object, layout), list (the popup list help, menus and pickers
│ share), card (the K card), status_bar, document_bar, which_key,
│ command_line, theme, glyphs
├─ config/ paths, settings, keys_file, theme_file (TOML)
├─ storage/ document_file (RON), atomic save, backups, lock, state, watch (change polling)
└─ app/ action, mode, buffer, commands (keys every view shares), calls (`:` commands),
text_edit (a title being edited, rapid entry), registers; later App, panes
(split tree), jumps, portals (cache, backlinks, renames), update, render,
terminal (setup, teardown, panic hook)
text_edit (a node's text being edited, rapid entry), registers, panes (the
split tree), popup (help, menu, pickers, card); later App, jumps, portals
(cache, backlinks, renames), update, render, terminal (setup, teardown,
panic hook)
```
**Flow:** a terminal event comes in → the key engine turns keys into a typed
@@ -459,11 +516,19 @@ document actions go to the document's `Buffer` (the only place a document
changes: the edit, its undo step, the cursor and the marks), the rest change
the mode or the app → the screen is drawn from the state.
While a title is edited, keys go to the edit (`app::text_edit`) instead: when
While a text is edited, keys go to the edit (`app::text_edit`) instead: when
typing, a key the `insert` table binds is a command (Enter, Tab, Backspace…)
and any other key types itself; with vim keys, the key engine reads the `text`
table, where operators take motions as targets too (`dw`, `c$`, `dfx`). The
edit answers with actions like everything else.
edit answers with actions like everything else. While a popup is open
(`app::popup`), keys and clicks go to it the same way: through the `list` or
`card` table, or straight into its search. The help and the menu run what
you pick as if its keys were typed (`AppAction::Run`).
The panes (`app::panes`) are a split tree, apart from what each pane shows:
a view and one of the open documents. Only the focused pane is in the mode
(the others are drawn as in normal mode), and its document is the one the
actions change; a click focuses the pane under it first.
Edits travel as data (`EditOp`), so views never touch the document. A `Group`
makes several edits one undo step: a whole move-mode session, a mouse drag, a
@@ -478,6 +543,9 @@ trait View { // settled in stage 5
fn render(&self, frame: &mut Frame, ctx: &ViewContext); // draws the layout, changes nothing
fn command(&mut self, typed: &Typed, ctx: &ViewContext) -> Option<Vec<Action>>; // None: not mine
fn mouse(&mut self, gesture: Gesture, ctx: &ViewContext) -> Vec<Action>;
// Added in stage 7, with defaults:
fn status(&self) -> String; // its name in the status bar
fn cursor_area(&self, ctx: &ViewContext) -> Option<Rect>; // where the K card goes beside
}
// ViewContext: the document, the cursor, the mode, the theme and the view settings.
```
@@ -503,8 +571,8 @@ it.
| 4 | Command line: registry, parser, completion (popup + ghost text), history | `:` in the example |
| 5 | The shared `View` interface, `Action` and `Mode`, pulled out of stages 2–4 | the example runs through it |
| 6 | Text editor: typing, plus vim normal mode inside text | editing titles in the example |
| 7 | Outline and Note views; status bar, document bar, help, `K` card, right-click menu, Documents picker | the example with splits |
| 8 | App core: main loop, terminal setup and panic hook, buffers, splits, modes, jumps, marks, registers, files (load, autosave, reload, backups, locks, where you left off), config/theme/keys, portals, backlinks and renames, startup rules | `cumulus`: v1 |
| 7 | Outline and Note views; splits (the split tree); status bar, document bar, help, `K` card, right-click menu, pickers (documents, colors, borders, styles, tags) | the example with splits and two documents |
| 8 | App core: main loop, terminal setup and panic hook, buffers and panes (from the example into the app), visual and connect modes, jumps, marks, registers, files (load, autosave, reload, backups, locks, where you left off), config/theme/keys, portals, backlinks and renames, startup rules | `cumulus`: v1 |
| 9 | v1.1: Board, Search picker, `:tidy` and align, branch out, export/import | |
Each stage ends with `cargo build`, `cargo lint` and `cargo test` passing, and
@@ -538,7 +606,13 @@ one commit.
- **Canvas:** camera conversions, routing and junctions (small text snapshots),
hit-testing, nearest-node moves.
- **Text editing:** vim keys inside text driven key by key (motions, operators,
text objects, `.`, undo), rapid entry, empty titles, registers.
text objects, `.`, undo), rapid entry, empty titles, registers, bodies and
tags.
- **Views:** the outline and the Note view drawn on a test terminal (rows,
parts, drafts being edited), and driven by keys and clicks.
- **Panes and popups:** splitting, closing and moving the focus in the split
tree; lists (moving, searching, clicks), the help, the menu, the pickers and
the card, driven by their key tables.
- **The example:** its tests drive the whole loop on a test terminal, keys and
mouse in and the screen out, so what a stage says works is checked end to
end.