Commit Graph
8 Commits
Author SHA1 Message Date
nvrl 7f8d625a8d commands: one grammar for !, merged commands, a settings sheet, two-level help
A `!` now means force or everything and nothing else (`:w!`, `:search!`,
`:export!`, `:logout!`). A command that did a second thing behind its bang
takes a word for it instead: `:space new|name|rm`, `:list name|rm`,
`:task [add]|edit`, `:upload seal`, `:import zip [/]`. `:card` while reading
a document makes a card about it, so `:card!` is gone.

Merged: `:export` downloads what has focus, a file as it is or a document as
markdown (`:download` folded in); `:share [off|new]` replaces `:unshare` and
`:link`, and the list's `s` and `y` give way to it and the info sheet;
`:noh` replaces `:clear`; `:vault [unlock|lock|passwd]` replaces `:unlock`,
`:lock` and `:passwd`; Esc in the list puts down what `m` picked up before it
closes the document, replacing `:unmark`.

The old spellings run as their new lines for one release through a table in
commands.ts; help and Tab leave them out, and the wiki lists them.

A settings sheet (`,` or `:settings`) holds the options, the vault, the
backup, the signed-in browsers, ssh keys and capture tokens. Each row runs
the command a line would. Bare `:set`, `:vault`, `:backup`, `:sessions`,
`:sshkey` and `:token` open it at their part.

`?` shows the keys and commands to start with, flagged in the keymap and the
command table; a second `?` (or `:help all`) shows all of them, and a filter
always searches all of them. Help rows are keyed by key and description, as
two contexts can share a label.
2026-10-22 15:35:36 +02:00
nvrl d8e72c688d files: a file belongs to a node, and a document holds its own
An upload while writing is now a file node of the document, through
POST /nodes/{id}/files, instead of a loose row of media that only the media
browser listed. It moves, seals, goes to the trash and comes back with the
document. Migration 0029 gives every embedded upload that had no node a
place under the document that embeds it (a living one before a trashed
one), keeping its media id, so no body changes; the sealed-folder triggers
now ask a document's folder for the files under it.

- nodes: `holds` and `place_for` say what may go where; a document holds
  files and nothing else, in moves, uploads and restores from the trash.
  A loaded document carries its files and whether its folder seals them.
- seal: a document moving into a sealed folder seals its files first.
- media: POST /media, GET /media and DELETE /media/{id} are gone, and with
  them MediaBrowser and :media.
- import: `plan/` beside `plan.md` comes back as the document's files, the
  shape export writes; an older export's media/ goes to the first document
  that embeds each file.
- sftp: a document's files are `<slug>/` beside its `.md`, listed once it
  has any, holding files only, moving with the `.md`.
- web: paste, drop and :upload while reading go to the document; the info
  sheet has a files section (Enter opens, i embeds, y copies how); the list
  shows +N on a document, za folds its files open, p drops marked files in.
2026-10-22 11:57:52 +02:00
nvrl 2233fa41a6 scratch: the scratchpad is the inbox, with ways out and a search
A note now leaves the scratchpad by becoming something else: `K` keeps it
as a document, as before; `C` makes it a card where `:card` would put one,
the first line its title; `A` opens `:append` with the document on screen
filled in, Tab completing any other title, and puts the note at its end.

`/api/capture` takes `to: "note"` and `to: "document"` (named as a link
names it), and `note`, the scratch note the text came from, dropped once
the text has landed. Appending keeps the revision before it and indexes
links and media, as a save does.

Migration 0028 adds `scratch_fts`; `GET /api/scratch?q=` searches it, and
`/` lists note hits under "notes" after the cards, Enter lowering the
drawer at the note.

The `c` capture line cycles its target with Tab: a card, a note, or a
timed line in today's entry, which `:today <text>` now writes.
2026-10-22 11:22:55 +02:00
nvrl ccc91028e7 editor: one editor, and everything written saves itself
TextEditor.svelte is folded into Editor.svelte. A card's description and a
note in the scratchpad are written in the same editor as a document, with
the same `[[` completion, and kept the same way: a new Writing (writing.svelte.ts)
stashes each change in localStorage and sends it to the server once the
typing stops, retrying a server that cannot be reached and recovering a
draft a dead tab left behind.

The keys out are the same everywhere: `:w` saves sooner, `:q` or Esc in
normal mode leaves with what is waiting written first, and stays where that
fails; `:q!` lets go of what is not saved. The store's describing and
scratch-editing flags are getters over the one `writing`.
2026-10-22 10:57:56 +02:00
nvrl b8b3641e6e cards: a document and its cards, seen from both ends
A document now lists the cards about it: the ones whose notes it is and
the ones whose description links to it. GET /nodes/{id}/cards answers
that, and the node itself carries it as `cards`. A line under the
document's meta line says what is still open and when it is first due;
it and `gc` open a new cards part of the info sheet, where j/k picks a
card, Space, H/L, D, a and `:` act on it, and Enter turns it over on its
board. `c` while reading a document makes a card about it.

Card verbs act on the card in focus wherever it is looked at: the
board's cursor, the card turned over, the agenda's highlight, the card
picked in the info sheet, or a document's only open card. patchCard,
sendCard and toggleDone take that card, so patchAgendaCard,
sendAgendaCard and finishCard are gone, and :due, :repeat, :label and
:done no longer refuse to run away from the board.

Migration 0027 adds card_links, links for a card's description: indexed
on every write, backfilled on start, followed and rewritten on a rename
or move like a document's, and claimed when a title they named appears.
It also adds cards_fts over title, description and checklist steps;
GET /cards?q= searches it, and / lists the cards found after the nodes,
Enter turning one over on its board.
2026-10-22 10:45:20 +02:00
nvrl 5684614d0a tiles: the board, the agenda, the calendar and a card's back are tiles
The special workspace was a second layout beside the tiles, with its own
focus, its own Tab, Esc and q, and a returnTo flag to find the way back.
The views are now tile kinds instead: opened beside what is on screen,
walked with Alt-h/j/k/l and gt/gT, closed with q.

- Tile gets a kind: node, board, agenda, calendar or card. view,
  specialFocus, returnTo and the special context are gone.
- A trail of focused tiles: closing one goes back to the one before, so
  q on a card's notes or a calendar day returns to the view.
- A view is never replaced by what is opened from it; that opens beside.
- S tiles the board, agenda and calendar ahead of the documents, or puts
  every view away. :plan, with :special kept as an alias.
- The card sheet is a card tile beside the board, following its cursor;
  leaving it while writing the description saves what is written.
- Spaces remember their views; with a view focused, a space switch takes
  the views along instead of leaving copies behind.
- Card commands check what has the focus rather than the special view.
2026-10-22 10:18:50 +02:00
nvrl 26b3c686d2 sheets: one Sheet component, and the info sheet over a document
Every overlay is drawn in Sheet.svelte: the header, the close button, the
footer of keys and the list cursor kept on screen, written once instead of
in ten copies. Overlays open and close through openSheet and closeSheet.

The outline, history and backlinks sheets and the share bar are one info
sheet with a part for each, Tab between them. gi opens it, gO, gh and gb open
it at their part, and so does a click on the line under the title. The
buttons in the document header are gone; the meta line says when the
document is public, and a phone gets edit and info under the text.
2026-10-22 04:07:42 +02:00
nvrl 0eabcb2333 keys: one table drives dispatch, help, footers, the rail and the wiki
keymap.ts lists every key with its context, action and help line.
actions.ts holds what each one does, typed against the table so a key
without an action, or an action without a key, does not compile.
modes.ts stacks the contexts (always > sheet > drawer > workspace >
writing > focused tile > special > global) and writes the two-key
pending logic once. App.svelte's 480-line onkeydown is now one call.

Help, the panel footers (a shared Keys component), the rail's keycaps
and Commands.md all read the table; the wiki gains the card and
scratchpad key tables.

One fix on the way: Ctrl-S in the editor no longer saves twice, which
could make the second save fail as "changed somewhere else".
2026-10-22 03:42:19 +02:00