26 Commits
Author SHA1 Message Date
skkeyeandClaude Opus 5.5 cc1b9dc11a Release v1.1.1
The board fixes since v1.1.0: columns and cards drawn exactly as the
canvas draws boxes, live dragging, cards dragged out into columns of
their own, and columns dragged among and into other columns. The user
tried them all and asked for the bump.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 14:41:25 -04:00
skkeyeandClaude Opus 5.5 09f8b048d6 Drag cards out into columns, and columns among and into columns
The user wants to drag a card out between columns to make a new column,
and to drag columns to reorder them or put them inside other columns.

Their pick for where: the row of titles, the gaps between columns and
the space past the last one are among the columns. Something dragged
there becomes a column, before the column under the mouse on its left
half and after it on its right half, after the one to the left in a gap.
Anywhere else it goes into the column under the mouse by the card rules,
so a column dragged down into another one becomes a card, its own cards
its block. A column's title no longer means "its first card"; the top
half of its first card does that. The root's column stays first and
can't be dragged (the user's pick): it says so.

The board holds still around a drag. Besides the kept widths, the room a
dragged column took stays empty while it isn't a column (Drag.room):
without it, the columns to its right slid left under the mouse each
time it stopped being one, and the card landed a column too far.
Dropping it back in that room makes it that column again.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 14:17:04 -04:00
skkeyeandClaude Opus 5.5 38eca3c8c3 Draw the board as the canvas draws boxes, and drag cards live
The user found the board's look off from the canvas's: a block's C was
gray around a white card, borders ignored the node's style, a folded
column said nothing, and dragging felt wrong.

Columns and cards now go through the canvas's line layer, with the same
rules as Scene::add_borders: the node's border style and color, thick in
the accent color for the cursor, thick in the visual color for the
selection. A block's bracket and foot are drawn in its card's own line
and color, so the C is one shape and its joint comes out as ├, ┣ or ╠.
Tags and badges sit in the bottom border through a footer() shared with
the canvas renderer. Columns show their tags and badge too, so a folded
column says +N, and a column's title can be typed in its top border
(it wasn't shown as typed before).

A drag now moves the card live, as on the canvas (the user's pick), all
one undo step: by the row under the mouse, before a card on its top
half, after it or into its block on its bottom half, out at a foot,
first on a column's title, last below the cards. Columns keep their
widths while dragging, or a column that narrowed would slide the one
under the mouse away and the card would chase it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 13:49:48 -04:00
skkeyeandClaude Opus 5.5 3716919db3 Add the board, and finish v1.1 (stage 9e)
The board is the user's design: the document as lists and blocks, the
way Scratch nests blocks inside a loop. Each node without a parent (the
root, then each loose node) is a column with its title in the top border;
its children are cards in it, one under the other; a card with children
on show wraps them in a C: a joint at its bottom left, a bracket down the
left two cells further in, and a foot closing it. Blocks nest as deep as
the tree does. The columns by tag or color the first design had are
dropped (the user's pick), and :board takes no arguments any more.

j and k go down and up a column in reading order, into the blocks; h and
l go to the column beside, onto the card nearest the cursor's height.
Titles are typed right in their cards, and visual mode selects in
reading order as the outline does. <Space>vb or :board shows it.

Move mode (M, the user's pick) moves the card through the tree: h and l
to the end of the column beside, j and k past the cards around it, into
an open block and out of one at its end. A column's own node trades
places with the loose column beside it; the root's column stays first.
A drag does the same with the mouse: dropped on a card it goes after it,
on a block's card into it, on a column at its end.

The fallback message for a key a view ignores now names the view ("does
nothing in the board view"). The version goes to 1.1.0: stage 9 is done.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 13:05:05 -04:00
skkeyeandClaude Opus 5.5 893edbda9f Search every document (stage 9d)
<Space>/ (the user's pick), or :search text straight to the best match,
searches every document cumulus knows of: the open ones (the shown one
first), the ones opened lately, the .cum files in this document's
folder, and every document their portals and backlinks lead to, however
far (the user's pick; up to 200). Open documents are searched as they
are, the others as their files have them.

It's the / popup with a list of documents to search: one list, best first
whatever the document, each match with its document's name at the end of
its row (the user's pick), the note beside it from that document. Enter
goes to the match through the jump list's GoToPlace, opening a closed
document.

n and N then go through every match, document to document (the user's
pick), going round. The matches are kept in the last search as they were,
as vim's :cnext goes through a :vimgrep list: searched again from each
document, equal matches would trade places and n would bounce between two.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 12:15:04 -04:00
skkeyeandClaude Opus 5.5 9d15a054f2 Export to Markdown or text, and import text as nodes (stage 9c)
:export md writes the document as Markdown headings in the clipboard's
format (the user's pick): # for the root and each loose node, ## for
their children, down to ######, the tags between --- lines, then the
body. :export txt writes an indented outline, tags after each title and
the body under it after "| " (the user's pick), from the new
storage::plain_text. The file goes next to the document, named after it,
or where it's told; as vim's :w to another file does, an existing file
needs :export! (the user's pick). Typed in visual mode, :export writes
just the selection, named after its first branch (the user's pick).

:import file reads Markdown headings, a list or indented lines with the
clipboard's reader, now also taking #tags at the end of a line and "| "
body lines, so a text export reads back whole. The nodes go under the
cursor's node, laid out as a mind map, as one undo step (the user's
pick).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 11:46:04 -04:00
skkeyeandClaude Opus 5.5 5888d143fd Branch a branch out into a document of its own (stage 9b)
<Space>o (the user's pick), :branchout [file] or the right-click menu
moves the cursor's branch into a new document, next to this one and
named after the branch's title (-2 when that's taken), or at the path
given. Its top node becomes the root, in the middle of the canvas, and
the nodes keep their ids, so the links among them, the small and capital
marks on them and the jump lists still find them.

A portal to the new document takes the branch's place (same spot in the
tree and on the canvas, same branch line) as one undo step, with a new
EditOp::BranchOut; u brings the branch back while the new file stays on
disk, as after :new. Then the pane goes through the portal (the user's
pick), so Ctrl-o comes back and the breadcrumb starts with the document
it came from.

Portals inside the branch move along (the user's pick), their paths made
from the new file's folder, and their documents' backlinks follow. Links
between the branch and the rest can't follow, since links stay inside a
document, and the message counts them. The root and portals themselves
can't branch out.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 11:25:57 -04:00
skkeyeandClaude Opus 5.5 3b8f7c0b3c Test the chart key, a plain :tidy and :tag on a selection
Three things the stage 9a summary lists, run end to end before listing
them: <Space>=c, :tidy with no layout (a mind map), and :tag on the
nodes selected when : was typed.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 10:42:44 -04:00
skkeyeandClaude Opus 5.5 13a603837e Tidy a branch and line nodes up (stage 9a)
The first small part of stage 9 (v1.1). <Space>= then m, c or g (the
user's pick: leader menus), or :tidy map|chart|grid, lays out the
cursor's branch while its top node stays put: a mind map puts each node
in the middle of its children (the user's pick), an org chart puts them
side by side below, and a grid makes a block of cards beside the node
(the user's pick), a card's own branch going along as a mind map. Every
node of the branch gets a place, folded away or not (the user's pick),
as one undo step, and the message says when the branch now covers nodes
outside it.

The lines follow the layouts: a parent whose children are all below it
sends its branches down to a shared bend, and a new child of it goes
beside the last one; a grid card behind another isn't joined by a line,
which would look like it joins the two cards.

In visual mode, <Space>a then h, l, k, j or c lines the selection up on
the box around it, each node bringing its branch along, and : opens the
command line on the selection: :align and :tidy take it, and so do
:color, :border, :style, :tag and :fold, as one undo step. The layouts
are pure functions in view::canvas::arrange, applied as one
EditOp::Reposition. Layout and Side moved from the parser to the model
so keys can name them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 10:42:00 -04:00
skkeyeandClaude Opus 5.5 95c6c3ca37 Test connect mode's named styles, n and the Note view
Three things the stage 8d summary lists, checked end to end before
listing them: a named line style picked with <Space>s, aiming with n
after a search, and connecting from the Note view, where l goes to the
next sibling.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 08:25:52 -04:00
skkeyeandClaude Opus 5.5 ebe8a5988e Add connect mode, portals, backlinks and renames (stage 8d, v1)
Part 8d, the last of stage 8, and with it everything on DESIGN.md's v1
list.

Connect mode (C): the cursor goes to another node, a dashed arrow in the
visual color follows it, and Enter links the two; then the cursor goes
back to where C was typed (the user's pick). d removes the line between
them (a branch is cut, and the child comes loose), > puts the node under
the other one, and <Space> a, l, c, s and t style the line as you watch,
making it when it isn't there yet. Everything connect mode changes is one
undo group, and Esc takes it back with History::cancel, which leaves
nothing to redo. From visual mode every selected node connects, and the
line pickers go back to connect mode when they close.

Portals show their document live, from a cache of what each document
file holds (open documents from their buffers, the others from their
files, looked at every second): the root's title, its color and how many
nodes it has, or ? when the document isn't there. Enter or gf goes
through, as a jump, and the pane's breadcrumb starts with the documents
it came through. <Space>p types :portal (the user's pick): a path as :e
takes it, or the title of a new document. Backlinks are put right
whenever a document is opened or saved; the root shows how many, the
Note view lists them, gu goes up to them (the user's pick) and
:backlinks lists them.

File names follow the root's title: when it changed, the next save
renames the file (-2 when the name is taken; a folder's default document
keeps its name), and the portals pointing at it, its backlinks in the
documents it leads to, the recent documents, the capital marks and the
jump lists follow. A portal whose file was moved by hand finds its
document in that folder by uid. Portals in a register keep full paths,
so a pasted portal leads to the same document from any folder.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 08:24:43 -04:00
skkeyeandClaude Opus 5.5 bd819409f4 Make p paste as children and P as siblings below
After trying part 8c, the user found p and P doing the same thing on the
canvas: both pasted a sibling below the node (P only differed in the
outline's order). Their pick: p pastes under the node, as its last
children, the way a adds a child; P pastes the next siblings, below it,
where o adds one. ]p went away, since p does what it did.

Inside a title p and P still paste after and before the text cursor, as
in vim: they're their own commands (paste-after, paste-before), and the
node ones are paste-as-child and paste-as-sibling.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 05:05:00 -04:00
skkeyeandClaude Opus 5.5 7bec5bf3fc Add visual mode, node registers, search and the jump list (stage 8c)
The rest of vim, on nodes. Visual mode takes in what lies between where
it started and the cursor: on the canvas, every node the rectangle from
one end's box to the other's touches; in the outline and the Note view,
the nodes in between in reading order. V takes whole branches, Ctrl+click
and Ctrl+drag pick with the mouse, and the operators take exactly what's
selected: d, y, > and <, M, and the pickers on every node at once.

Registers now hold text or nodes, so yy, dd and x keep what they take and
p, P and ]p paste it, layout and links included. "+ is the system
clipboard through arboard: nodes go there as Markdown in the user's
format (## headings, a --- tag list, the body), and come back whole while
the clipboard still holds them. clipboard = "unnamedplus" makes plain
yanks use it, as in vim.

. repeats the last change made with keys, with the text typed after it.
/ opens a Telescope-style search: fuzzy matches over titles, tags and
bodies, best first, with the note of the one you're on beside them; n
and N go on with it, and :find searches straight away. Each pane keeps a
jump list for Ctrl-o and Ctrl-i that crosses documents and reopens closed
ones. Capital marks lead into any document and, like the small ones, are
kept in memory.ron. gd follows a cross-link, and :marks, :jumps and
:registers list what they hold.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 04:12:27 -04:00
skkeyeandClaude Opus 5.5 abe3dc1d84 Read config.toml, keys.toml and themes, and open them with :config (stage 8b)
The config folder now sets everything: config.toml the settings (now
also `theme` and `editor`), keys.toml the keys, and themes/<name>.toml
the theme, laid over the built-in one, so a theme only needs what it
changes. Each file is applied again a second after it's saved; a
mistake only drops its own line, and the status bar says what's wrong,
naming the file.

:config lists the three files with their folder; Enter hands the
terminal to your editor (the editor setting, $VISUAL, $EDITOR, else
notepad or vi), writing the file first if it's missing, with every
option at its default behind a #, explained (keys.toml lists every
command by name). :theme switches themes until cumulus quits, like
:set.

The built-in theme gets the named styles the user picked, each also put
on by its tag: question (yellow, dashed), important (red, thick) and done
(gray, its title faded); and link styles blocks and supports, whose
label shows on a link without its own. Themes can also set [modes],
[node], [root], [branch] and [link].

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 23:55:11 -04:00
skkeyeandClaude Opus 5.5 f6dc4564aa Run cumulus for real: the app core and its files (stage 8a)
The playground becomes app::App, and `cumulus` runs it: the main loop
with terminal setup and a panic hook, and the startup rules (./ideas.cum,
else ~/ideas.cum, made the first time; files and folders by name;
`cumulus new`; --paths).

The documents' files:
- autosave a second after the latest change (`:set noautosave` for
  vim-style :w), [+] in the document bar for unsaved changes; quitting
  saves first; without autosave :q refuses, :q! drops, ZZ saves first;
- a file changed outside cumulus is read again as an undo step; with
  unsaved changes here too, cumulus asks which to keep; a file with a
  mistake in it holds autosave until it's fixed or :w saves over it; a
  deleted one waits for :w; nothing is reloaded under an edit;
- the day's first save backs the file up to the data folder (30 days);
- a document open in another cumulus is read-only ([RO]) until that one
  lets go: OS file locks in the data folder, so a crash leaves none;
- where you left off (cursor, zoom, scroll), the recent documents (now
  in the documents picker) and the command history, in memory.ron;
- :e (alone: read it again; ! drops changes), :new, :bd, :w, :wa, :x,
  :qa, <Space>i for :in, and :set for every setting. glyphs=ascii now
  reaches the frames and bars too, not just the canvas and outline.

Stage 8 comes in four parts with a commit each (the user's choice); 8b
is the settings files. The example is now a playground running the app
on copies of the sample documents in a temporary folder, and the
end-to-end tests moved to src/app/tests.rs, with tests for the files.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 23:18:21 -04:00
skkeyeandClaude Opus 5.5 e6f3c06ecc Scroll sideways with Shift or Alt and the wheel, and in the outline
A wheel that tilts (or a touchpad) already panned the canvas sideways,
but only when the terminal passes those events on, and many don't:
Windows Terminal only does since 1.24, and Windows' own console layer
can drop them. The wheel with Shift held now scrolls sideways too, as in
most apps, and so does Alt, since Alacritty and Windows Terminal keep
Shift with the mouse for selecting text.

The outline scrolls sideways as well (the wheel, zh and zl), for rows
wider than its pane: a deep tree or a long title. Clicks land where the
rows are, however far they're scrolled, and when the cursor moves its
title comes back into view.

Fixed on the way: the wheel turned sideways over the help, the menu, a
picker or the K card moved it up.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 19:48:52 -04:00
skkeyeandClaude Opus 5.5 c587c42115 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]>
2026-10-01 19:10:09 -04:00
skkeyeandClaude Opus 5.5 84aefbecdb Edit titles in their boxes, with vim keys inside the text
Titles are typed right in their boxes on the canvas: the box grows with
the text, the terminal's cursor sits in it (a bar while typing, a block
on the letter with vim keys), and the border turns the insert color.
`i`, `A` and Enter edit at the end, `I` at the start, `cc` and `S` type
the title anew. The document follows the text as it's typed, so the
layout stays current, and the whole edit is one undo step.

Esc gives vim's normal mode inside the text (TextEditor, in ui/): h l w
b e 0 ^ $, f t F T with ; and ,, the d c y operators with any of those
motions or the iw aw i" a" i( a( text objects, x X s S D C Y, r ~, p P,
counts, u and Ctrl-r for the edit's own changes, and `.` for the last
one, typing included. j k gg G and J work on lines, for bodies. It
follows vim where it's quirky too: cw acts like ce, dw stops at the end
of the line, Esc steps back onto the last letter. Keys have two new
tables, `text` and `insert`, and in text an operator takes motions as
targets (`dw`, `c$`, `2d3fx`), which which-key lists.

Rapid entry: after `o`, `O` or `a`, the new idea's title is typed at
once; Enter starts the next idea, Tab puts the one being typed under the
idea above, Shift-Tab takes it out a level, and Enter on an empty idea
stops. An idea left empty goes away without a trace in the undo history
(a group whose edits cancel out leaves no step); a title left empty
comes back as it was. Inside a title, `o` and `O` start a new sibling.

Registers are shared by the whole app, so text yanked in one title
pastes into another; `"a`-`"z` and `"_` work, and `"+` stays inside
cumulus until the app core connects the clipboard.

The mouse while editing: a click in the text moves the text cursor, a
click anywhere else keeps the text and finishes the edit, and a
double-click on a title starts editing at that letter.

`>>` and `<<` now move nodes: under the node above, as its last child,
or out a level, right after the old parent, with counts taking in the
next siblings.

The command line's input became TextInput, line-aware so the editor can
use it for bodies too; bodies themselves get edited in the Note view.
The example's tests type every key above into the app and check the
text and the cursor after each one against what vim does.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 17:45:40 -04:00
skkeyeandClaude Opus 5.5 6eedbe0ce2 Pull the view interface, actions and modes out of the canvas example
The canvas example did everything itself; now it runs the way the app
will. The key engine turns keys into commands, the focused view answers
with actions, and the commands every view shares (undo, marks, adding,
deleting, folds, tree moves, modes) answer the rest. A view can still
give a key its own meaning, since it gets the first say. `:` lines become
actions the same way (app::calls).

- View trait: kind, contexts (its key tables), layout, render, command
  and mouse. layout comes before render because a view keeps the frame
  it drew, to match clicks against, and follows the cursor with its
  camera; drawing changes nothing. CanvasView owns the camera, the last
  scene and the mouse drag; it reads the rest from a ViewContext.
- Edits travel as data (EditOp), so views never touch the document.
  Buffer::apply is the one place a document changes: the edit, its undo
  step, where the cursor goes, marks and `''`.
- Mode holds each mode's own state: move mode carries its Grab (whole
  branch or not), the command line lives in Mode::Command.
- Undo groups: a whole move-mode session or mouse drag is one undo step,
  built up as it goes. After an undo the cursor lands on a node the
  change added or removed, before the others it touched.
- Actions run in order, and a problem stops the rest.

Small improvements on the way: zz centers the middle of the node, :find
says which match it's on, :unlink with no links says so, folding a node
without children says why nothing happened, and a captured idea is
placed next to a new Inbox even on the first :in.

The example has end-to-end tests now: they type key sequences and mouse
gestures into it on a test terminal, and `cargo test` runs them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 04:46:05 -04:00
skkeyeandClaude Opus 5.5 57ba2c275d Make marks and counts work, and the completion popup a setting
Marks: the engine read `ma` and `'a`, but the canvas example only said
they'd come later. It now sets and jumps to marks, and `''` goes back to
where the cursor was before the last jump (a mark, gg, G or :find).
Which-key lists `'` after `'`.

Counts on operators now mean something on nodes: `3dd` deletes this node
and the next two siblings, with their branches, the way vim's `3dd`
deletes three lines (Document::siblings_from). Counts before the operator
and before the target still multiply, and which-key now says what they
add up to: after `2d3`, the `d` entry reads "6 nodes: this one and the
next 5 siblings, with their branches".

The completion popup can now wait for Tab, like vim's wildmenu: the
`completion_popup` setting is "as-you-type" (the default) or "on-tab".
The config file comes with the app core; until then the example takes
`:set completion_popup=on-tab`.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 04:17:41 -04:00
skkeyeandClaude Opus 5.5 bfc184f5ef Add the command line: commands, completion, ghost text and history
`:` opens a vim-style command line. Every command is described once, in
a typed table (name, the short form that still works, aliases, a `!`,
its arguments and what it does), so parsing, completion and the help can
never disagree. Short forms work as in vim (`:e`, `:vs`, `:q!`, `:x`),
and a test checks that no typed name can mean two commands.

Parsing turns a line into a typed Call, checking every argument against
what the app offers (open documents, nodes, colors, styles, settings),
or says what's wrong in words: the usage when an argument is missing,
the choices when a word isn't one, "did you mean :fold?" for a typo.
Documents and nodes match fuzzily (`:b gpl` finds Garden plans).

While typing, a popup above the word lists what can finish it (command
names by prefix, choices, files from the folders on disk, documents and
nodes fuzzily), with Tab and Shift-Tab putting them in the line. Ghost
text after the cursor comes from the history first, like fish's, then
from the best candidate; → or Ctrl-e takes it. Up and Down browse the
lines that start with what was typed. The line itself is a small input
that steps over whole characters, accents and emoji included.

The canvas example opens it with `:` and runs a handful of commands:
:fold, :color, :border, :tag, :focus, :rename, :in (to an Inbox),
:link, :unlink, :find, :version and :q.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 03:53:51 -04:00
skkeyeandClaude Opus 5.5 c2e62de172 Add the key engine, which-key and keys.toml
Keys now work the way vim reads them. A key press becomes a Key (with vim
notation for writing keys: `<C-w>v`, `<leader>c`, `<<`), and the engine
collects counts (`12j`), registers (`"+p`), sequences (`gg`), operators
with their targets (`dd`, `dab`, `2d3d` multiplies to 6) and keys that take
a character (`ma`, `'A`), then hands over a typed Command. Every command
has a name and a help text in one table, and the default keys live in one
table per place they work (motions, normal, canvas, visual, move, connect,
lists).

keys.toml changes keys per section, with the leader configurable and
"nothing" to unbind. Each mistake is skipped and reported in words, with a
suggestion for mistyped command names, and a key that would hide a longer
one is reported too. The which-key popup reads the same tables: it shows
what can follow the keys typed so far, in skyshift's look and place, with
the leader menu instant and other prefixes after 300 ms. The mouse reader
turns button events into presses, double-clicks, drags and scrolls.

`Direction` moved from the glyphs to the model, since input needs it too.
The canvas example now runs on all of this, with a two-line keys.toml of
its own that makes `q` quit.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 01:54:06 -04:00
skkeyeandClaude Opus 5.5 e097e53a85 Make branch lines take their parent's color
A node's color now flows down the lines to its children, mind-map style:
Watering's teal colors the lines to Rain barrel and Drip line. It used to
color the line from the root down to Watering itself, which also left the
shared bus of a parent's branches in whichever child's color was drawn
last. Branches follow their parent by default, and stay dim when the
parent has no color.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 01:40:24 -04:00
skkeyeandClaude Opus 5.5 3b58d6494d Add the canvas engine and a canvas playground example
The canvas draws a frame in three steps. Scene::build works out what's
shown and where: folding decides which nodes show, boxes are sized from
their wrapped titles (with tags and a +N badge in the bottom border), the
camera turns canvas positions into screen cells, and every branch and
cross-link gets a right-angle route. The line layer records which arms
meet in each cell, so borders and lines join with the right box-drawing
character (├ ┼ ┨ ╭), in any mix of light, thick, double, dashed and dotted.
Rendering then writes lines, arrowheads and labels, and the nodes on top.

Branches leave sideways and bend near their parent, so siblings share one
bus; cross-links take the wider gap and carry their label on the longest
level run. Far zoom keeps the full width and halves the height (one line
per node), Overview shows dots. hjkl picks the nearest node within 45° of
the direction, and new nodes find a free spot next to their parent or
sibling. The theme works out looks in layers (default, tag style, named
style, the node's own), with a mid-tone palette for dark and light
terminals, and an ASCII fallback for fonts without box drawing.

`cargo run --example canvas` opens a sample document to move around,
zoom, fold, edit and drag with the mouse. The tests compare rendered text
against the DESIGN.md mockup.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 01:17:38 -04:00
skkeyeandClaude Opus 5.5 69aa7eee58 Add the data model and the document file format
The model holds the rules: a document is a tree under one root, with
loose nodes beside it and cross-links between any two nodes. Every change
runs as a transaction that rolls back on error and returns an undo step
(the old and new values of whatever it touched), so undo and redo need no
code of their own per command. Text from outside (titles, tags, names) is
checked once, when it becomes a typed value. Folding (Open, Auto, Closed,
plus focus) is one function that every view will share.

storage::document_file reads and writes `.cum` files in RON, with
multi-line bodies kept readable, `\n` line endings on every OS, and errors
that name the node they're about. The tests cover the tree rules, 500
random edits undone and redone step by step, folding, and the file format
(the example from DESIGN.md is written back character for character).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 00:54:49 -04:00
skkeyeandClaude Opus 5.5 0e03c396bf Add the project skeleton and the approved design
Cargo.toml with the release profile and lints, the toolchain pinned to
Rust 1.90.0, a build script that records the git commit for
`cumulus --version`, and rustfmt settings and cargo aliases (`cargo lint`,
`cargo linux`) as in skyshift. DESIGN.md holds the design approved after
the question rounds; README.md has build instructions and the planned keys.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 00:42:28 -04:00