summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/design.typ44
-rw-r--r--docs/fs.md7
-rw-r--r--docs/helix-keys.md8
-rw-r--r--docs/tags.md60
4 files changed, 73 insertions, 46 deletions
diff --git a/docs/design.typ b/docs/design.typ
index 82bafb49..8e5f7e6e 100644
--- a/docs/design.typ
+++ b/docs/design.typ
@@ -530,9 +530,9 @@ Each pane kind keeps its storage and operations together in its own file
image pane in `image.zig`), reached through `panes.zig` beside `Pane`.
`layout.zig` owns placement and presentation state. `pardes.zig` handles input
and cross-pane state directly, without a pane vtable; the rest of the editor
-is split by thing as acme is: `edit.zig`, `normal.zig`, `look.zig`, `exec.zig`,
-`mouse.zig`, `Messages.zig`, `Pipe.zig`, `colors.zig`, `surface.zig`,
-`body_layer.zig` and `dump.zig`. Integration fixtures live
+is split by thing as acme is: `Text.zig`, `edit.zig`, `normal.zig`, `tagline.zig`,
+`look.zig`, `exec.zig`, `mouse.zig`, `Messages.zig`, `Pipe.zig`, `colors.zig`,
+`surface.zig`, `body_layer.zig`, `tag_layer.zig` and `dump.zig`. Integration fixtures live
in `test/panes.zig`, `test/output.zig`, and `test/pdf.zig`.
= State
@@ -770,33 +770,35 @@ pair per theme, and the three per-button tints and the dimmed extra cursors are
mixed off it, so what stays fixed is the distinction between buttons and not the
colours.
-`Drag` is a `union(enum)` with six arms (`pardes.Drag`): `none`,
-`border_v`, `border_h`, `move`, `tag`, `select`. `border_v` carries an optional
+`Drag` is a `union(enum)` with six arms (`mouse.Drag`): `none`,
+`border_v`, `border_h`, `move`, `column_move`, `select`. `border_v` carries an optional
`corner`: when the press lands on a cell that is both a column's vertical border
and one of the two adjoining columns' own horizontal borders, the one drag moves
*both* boundaries — never three, and when both columns happen to be split at the
grabbed row the left one wins, so the gesture that existed before is bit-for-bit
unchanged.
-== The tag is a command line
+== The tag is a text
-A tag is one line: a live prefix (mode indicator, cwd or path) plus an editable
-tail, and the tail gets the full modal editor. The coordinate space is UTF-8 byte
-offsets into the *whole* rendered tag, prefix ++ tail, always on grapheme
-boundaries (`Pane.tag_col`). The prefix is live chrome, so it is
-selectable, yankable and executable but READ-ONLY: every edit op measures from
-`edit0` — the first editable byte — and does nothing left of it.
+A tag is a `Text` (`Text.zig`), as a body is: acme's `Text`, one per
+`what` — the body, the pane's tag, the prompt line, a column's tag and the
+workspace tag. Each holds its own cursor, selections, mode and undo, so tags
+are edited by the same `edit.zig` and `normal.zig` code as bodies, and the one
+key they do not share is `:`, which moves between a pane's body and its tag.
+A tag holds any number of lines; a pane's tag takes a row per line up to
+`MAX_TAG_ROWS`, each drawn as a tag layer of its own.
-`tag_tail` is a fixed `[max_tag_tail]u8`, and the bound IS the storage
-(`limits.max_tag_tail`): every writer — `appendTag`, `tagInsert`,
-`restoreDumpTail`, the 9P `tag` file — refuses input that does not fit
-rather than truncating it. The schema limit and the buffer therefore can never
-disagree, which is what lets a dump reader reject data before copying it into a
-pane.
+A pane's tag shows a live prefix (path, dirty marker, PDF page) before the text
+it owns, and that prefix is computed at every read, never stored
+(`tagline.tagPrefix`). The Text's coordinates are offsets into its own text
+alone, so a rename or a save never moves its cursor. The one translation
+point is the whole line as shown: render, the mouse, Look, Exec and the 9P
+`tag` file see prefix ++ text, while keyboard motions and edits see only the
+text. Editing the path is a separate draft (`Pane.prompt = .name`) committed
+by Enter, since a buffer's name is not text it owns.
-A tag edit is always insert mode, so it hijacks the body's mode; `tag_mode`
-remembers what it hijacked and terminals restore it on exit, which is why
-clicking a tag never changes a pane's mode.
+The tag's text is bounded by `limits.max_tag_tail`: the 9P `tag` file and a
+dump reader refuse input that does not fit rather than truncating it.
= Diffing and presenting a frame
diff --git a/docs/fs.md b/docs/fs.md
index da4f4e68..c43034f6 100644
--- a/docs/fs.md
+++ b/docs/fs.md
@@ -180,7 +180,12 @@ back evaluates it, which is what acme(4) promises of its own `addr`.
The three flag files `dirty`, `mark` and `scroll` read `0` or `1` and take
`0` or `1`: whether the buffer differs from its file, whether a write pushes
an undo point (writing `1` pushes one now), and whether a write scrolls the
-pane. Truncating `tag` clears the part of the tag you may edit.
+pane.
+
+`tag` reads the whole tag as the pane shows it: the computed path, dirty
+marker or PDF page, then the text you may edit. A write appends to that text,
+newlines included, and a tag with more than one line takes a row per line on
+screen; truncating `tag` clears it, as acme's `cleartag` does.
Stats report real lengths for `index`, `status`, `look`, `exec`, `listeners`,
`name`, `body`, `tag`, `sel`, `ctl`, the range files and the flag files, and
diff --git a/docs/helix-keys.md b/docs/helix-keys.md
index 0813c193..64fa2e24 100644
--- a/docs/helix-keys.md
+++ b/docs/helix-keys.md
@@ -117,15 +117,15 @@ language-backend queries, and the shell pipe.
| `Esc` (insert) | back to normal mode, cursor right after the insertion (no vim left-step) | | helix-verified |
| `Enter` (normal) | acme **look** chord: EXPLICIT selection, else file-ish word under cursor | pardes-specific, keep (helix normal-mode Enter unbound). Covers helix `gf`. Implicit motion residue falls back to the cursor word | pardes-specific |
| `Tab` (normal) | acme **execute** chord | pardes-specific, keep; explicit-selection rule as Enter | pardes-specific |
-| `:` (normal, body) | focuses the pane's tag in normal mode at its remembered cursor position (first entry starts at the commands). `h`/`l`, arrows, word motions and `0`/`$`/`^` move within the tag; `k` stays on its single line; `j` or `Esc` returns to the body. Uppercase `H`/`J`/`K`/`L` run `Left`/`Down`/`Up`/`Right` and enter the neighboring pane's tag. `K` beyond the top pane reaches the headers below. `y` yanks; Enter/Tab Look/Exec; `i`/`a`/`I`/`A` enter insert mode, where letters type normally. Explicit mouse clicks choose a new cursor position. | Each tag keeps its own cursor position during the session. Positions are UTF-8 byte offsets in the rendered prefix plus editable tail; file-name changes are staged as described in [editable tags](tags.md). | pardes-specific |
-| `K` (tag normal, topmost tagline) | focuses the column tag, then another `K` reaches the workspace tag. With `ColumnTags` disabled it goes directly to the workspace. `J` walks back down. Header arrows and `h`/`l` move by grapheme; word motions and `0`/`$`/`^` work too. `j`/`Esc` returns to the panel; lowercase `k` stays put. Enter/Tab executes in normal mode; `i`/`a`/`I`/`A` enter editing, where Enter is Look and Tab is Exec. | Column commands target that column's active pane, or its first pane when coming from elsewhere. Workspace and column text are independently editable and persist in dumps. See [editable tags](tags.md). | pardes-specific |
-| `Ctrl-w` + `h/j/k/l`/arrows | directional pane focus prefix — editor normal mode only | pardes' own window handling (helix window mode skipped, section C). Runs the SAME `Left`/`Down`/`Up`/`Right` builtins `SPC w h/j/k/l` runs; Raw **tty** mode forwards Ctrl-w to the child. Insert mode owns `Ctrl-w` = delete-word-back, so a tag being TYPED into swallows it; from a tag in normal mode (`:`) it moves focus to the neighbour's BODY, while the bare letters `h/j/k/l` there move to its TAGLINE (next row) | pardes-specific |
+| `:` (normal, body or tag) | in the body, focuses the pane's tag in normal mode at its remembered cursor (the first time, on `Save`); in the tag, goes back to the body; in a column or workspace tag, back to the active pane. The tag's normal and insert modes ARE the body's: every motion, selection, edit and undo works there, `0` meaning the start of the editable text. Enter/Tab Look/Exec the word under the cursor or the selection, and executing hands the keyboard back to the body first. Clicks choose a new cursor position and type into the tag. | Each tag keeps its own cursor during the session. Cursor, selections and undo are offsets in the tag's own text; the computed path/marker/page before it is seen by the mouse, Look and Exec but not by keyboard motions. File-name changes are staged as described in [editable tags](tags.md). | pardes-specific |
+| `Ctrl-w k` / `SPC w k` (pane with nothing above) | focuses its column's tag, then the workspace tag; with `ColumnTags` disabled it goes directly to the workspace. `Ctrl-w j` walks back to the panes, `Ctrl-w h`/`l` walk the column tags. Headers edit exactly as a pane tag does. | Column commands target that column's active pane, or its first pane when coming from elsewhere. Workspace and column text are independently editable and persist in dumps. See [editable tags](tags.md). | pardes-specific |
+| `Ctrl-w` + `h/j/k/l`/arrows | directional pane focus prefix — editor normal mode only | pardes' own window handling (helix window mode skipped, section C). Runs the SAME `Left`/`Down`/`Up`/`Right` builtins `SPC w h/j/k/l` runs; Raw **tty** mode forwards Ctrl-w to the child. Insert mode owns `Ctrl-w` = delete-word-back, so a tag being TYPED into swallows it; from a tag in normal mode it moves focus to the neighbour's BODY, as from a body, and from the top pane `Up` reaches the column and workspace tags | pardes-specific |
| `Alt-n` | new terminal below (outside raw tty) | shadows helix `Alt-n` TS sibling-select — skipped anyway (tree-sitter) | pardes-specific |
| `Alt-c` | move active terminal to a fresh column (outside raw tty) | helix `Alt-c` is change-noyank; the pardes window op wins (do-not-touch contract). `Alt-d` + `i` covers the behavior | waived (`alt-c-window-op`) |
| `Space` (normal, body) | starts the pardes LEADER: a key path runs the same builtin words used by tags and the topbar. The main groups are `f` files, `h` docs, `c` columns, `t` toggles/effects, `a` panel animations, `s` session, `j` jumps, `l` language, and `w` directional focus; `SPC ?` lists every path and `<prefix> ?` lists one group in `+Help`. The pending path appears on the active pane's transient body/message row. Esc or an unmapped key abandons it. Paths, Help rows, and dispatch are all generated from the builtin registry at comptime; the leader applies only to a BODY in normal mode because tags and tty programs own their input | pardes-specific; helix spends Space on pickers/LSP (section C), while pardes uses acme-style executable words |
| `SPC y` `SPC Y` `SPC p` `SPC P` `SPC R` | helix's clipboard menu on helix's own letters: yank the selection to the system clipboard (`ClipYank`) or the PRIMARY selection alone (`ClipYankMain`), paste the system clipboard after (`ClipPaste`) / before (`ClipPasteBefore`) the selection, replace the selection with it (`ClipReplace`) | the ONLY five words in pardes that touch the desktop's clipboard — `y`/`d`/`c`/`p`/`P`/`R` and the acme cut/paste chords are the internal register alone. Builtins rather than bare chords because a leader path names a builtin: they land in Help's index and are executable words like every other verb. One divergence: pardes keeps a single register VALUE where helix keeps one per range, so `SPC y` at N cursors joins them with newlines (`Pardes.setYank`, the divergence `msel-yank-paste` already waives). On a tty the write is OSC 52 out and the READ is OSC 52 back, which many terminals refuse or gate — so `SPC y` works there and `SPC p` can be a no-op | out of corpus |
| a paste from the OUTER terminal | one `Event.paste`, spliced in at the cursor | the tty shell enables bracketed paste and coalesces `paste_start`..`paste_end` into a single event; before that the bytes arrived as individual key presses and normal mode RAN them, which is how a pasted `d` deleted a line. The bytes deliberately never enter the yank register — clipboard and default register are separate stores in both directions | pardes-specific |
-| `/` (any pane) | pardes' own plain-substring search into a `+Search` output buffer: the tag takes the pattern, Enter fills the buffer, and its rows are ordinary look targets. Enter also GOES to the first row — the buffer is focused and then the step `n` is and the look Enter is run in it (`Pardes.lookFirstHit`), so `/foo` lands on the first hit with the matched span selected. A pattern that matched nothing opens its empty buffer and moves nothing | KEEP, do not touch; not in the corpus (helix `/` is regex search). Find and Grep answer with OTHER files and deliberately do NOT jump. The stepping half is the next row | pardes-specific |
+| `/` (any pane) | pardes' own plain-substring search into a `+Search` output buffer: the pattern is typed on a line of its own on the pane's notice band, Enter fills the buffer, and its rows are ordinary look targets. Enter also GOES to the first row — the buffer is focused and then the step `n` is and the look Enter is run in it (`Pardes.lookFirstHit`), so `/foo` lands on the first hit with the matched span selected. A pattern that matched nothing opens its empty buffer and moves nothing | KEEP, do not touch; not in the corpus (helix `/` is regex search). Find and Grep answer with OTHER files and deliberately do NOT jump. The stepping half is the next row | pardes-specific |
| `n` / `N` (any pane) | MOTION, not a jump: move the SELECTION to the next / previous look-able text and open NOTHING. Enter — the look chord — on what it leaves selected is what opens it | KEEP, do not touch; not in the corpus (helix's `n`/`N` walk regex search hits). What a step selects is the pane's GRAIN (`output_pane.Grain`, read in `Pardes.lookSpanIn`): in FREE TEXT — a terminal, a file, a PDF, a prose answer buffer — the largest whitespace-delimited run `look.resolve` can act on (`look.lookableSpan`, wrapper punctuation peeled off both ends), several to a line; in a RESULTS BUFFER one stop per ROW, the largest run its head resolves as (`look.lookableLineSpan`), because a row there IS one location and the words after it are the match rather than a second place to go; in a COMMAND list the whole line. The walk is a RING across PANES: every pane that has performed a Look, most recent first (`Pardes.look_src`), then the output buffers that have not, newest first, and only when both are empty the active pane. Exhausting a pane enters the next at its first (forward) / last (backward) span and the end wraps to the start, so `N` is the exact inverse of `n`. What it lands on becomes an EXPLICIT `vsel` with the cursor on its FIRST column, in the pane the walk focuses. ONE motion in every pane kind and every buffer kind — a PDF steps the `+Search` buffer its own search filled, `n` to select the row and Enter to jump. The single thing a buffer may change is that grain, and it changes it by BEING a kind of buffer rather than by a branch: `output_pane.Traits.steps` (a list of locations) makes a step take one row at a time, and `Traits.commands` makes it take the WHOLE LINE, because a command list (`ThemeSel`/`FontSel`) holds words to run and there is no path inside `Theme gruvbox` to pick out. Tab on what `n` selected wears the theme, which is the same middle click on the row is. `]d`/`[d` are helix's diagnostic motions, a different binding, and they do still jump to each diagnostic (`docs/lsp.md`) | pardes-specific |
| insert: printable text | file: real edit; terminal: typed run splice | | helix-verified (file) |
| insert: `Enter` | newline; keeps the current full indent levels and adds one 4-space logical tab when the text before the cursor ends in `(`, `[`, `{`, or `)` (including `})`) | plain lines match `insert_newline`; delimiter heuristic is pardes-specific | helix-verified (plain) / pardes-specific (delimiter) |
diff --git a/docs/tags.md b/docs/tags.md
index f299c859..ecca046a 100644
--- a/docs/tags.md
+++ b/docs/tags.md
@@ -44,34 +44,54 @@ asks; there bare `Del` gives the rows to the nearest document above, as it
always has. A collapsed pane is never asked about, and collapsed neighbors
are passed over: they only keep a weight for later.
-Left-click a tag to place its caret; drag to select text, then type to
-replace it. Arrow keys, Home, End, Backspace and Delete edit the line.
-Tags reveal the caret horizontally when text is wider than their column.
-Escape returns to the body, keeping command-text edits. The existing Exec
-and Look gestures still apply; the workspace tag is no longer an inert
-left-click target. Pasted text goes to the focused tag, not to the file or
-embedded shell beneath it.
+A tag is a text like a pane's body: pane tags, column tags and the
+workspace tag all edit with the body's own normal and insert modes, undo
+included, and may hold more than one line. A tag with a newline in it takes
+a row per line, up to eight: a pane's tag leaves its body at least one row
+and a collapsed pane shows only the first line; the column and workspace
+tags take no more than a third of the screen, and the panes below move down
+to make room. The path, the dirty marker and a PDF's page at the start of a
+pane tag are computed, never stored: the tag's cursor, selections and undo
+live in the text after them, so a rename or a save never moves the cursor.
+The mouse still sees the whole line -- a sweep selects across the path and
+the commands, and Look and Exec work on either -- but the keyboard moves only
+in the tag's own text: `0` goes to its start, not the path's.
-Keyboard entry returns to the tag's last cursor position. The first entry into
-a pane tag starts at its commands; clicking always chooses a new position.
-Each pane, column and workspace tag remembers its own position during the
-session. Shortened text clamps the saved cursor to a valid character boundary.
+Left-click a tag or a header to type into it at the click, in insert mode;
+tags reveal the caret horizontally when text is wider than their column.
+Esc is normal mode, where everything a body's normal mode does works, and
+Enter looks up and Tab executes the word under the cursor (or an explicit
+selection), in either mode. Executing gives the keyboard back to the body
+first, so `Del`, `Kill` and `Restore` never return into a tag that is gone.
+Pasted text goes to the focused tag, not to the file or embedded shell
+beneath it.
-In normal mode, `h` and `l` move within the tag, `k` stays on the single line,
-and `j` returns to the panel like Escape. Uppercase `HJKL` move between pane
-tags. From the top pane's `:` tag, `K` reaches the column and another `K` reaches
-the workspace; `J` walks back down. Enter or Tab on a header command in
-normal mode executes it, as before. `i`/`a`/`I`/`A` switch to editing the
-header. In insert mode, letters type normally, Enter is Look and Tab is Exec,
-as in pane tags.
+`:` is the one key a tag and a body do not share: in the body's normal mode
+it focuses the pane's tag in normal mode, and in the tag's normal mode it
+goes back to the body; in a column or workspace tag it goes back to the
+active pane. Each pane, column and workspace tag remembers its own cursor
+during the session; the first `:` into a pane tag starts on its `Save`. A
+tag's text changing under it (a 9P write, a shorter tag) pulls the cursor
+back inside it.
+
+Moving between tags is the window keys' job, as it is between bodies
+(`Ctrl-w` or `SPC w` with `h/j/k/l`): they move to the neighbouring pane's
+body. Up from a pane with nothing above it reaches its column's tag, then
+the workspace's; Down comes back the same way, and Left and Right walk the
+column tags.
+
+Search (`/`), pipe (`|`) and Save's path prompt are not typed into the tag:
+each gets a line of its own on the pane's notice band, with the body's
+insert-mode keys, and leaves the tag as it was.
Pane filenames and commands now have a single separator space rather than
generated right-alignment padding. Intentionally customized spacing is kept.
## File names
-Editing a file pane's name creates a draft. Enter confirms the new buffer
-name; Escape or leaving the tag cancels the draft. Confirmation changes the
+Clicking a file pane's name starts a draft of it, typed into at the click.
+Enter or Tab confirms the new buffer name; Escape or leaving the pane
+cancels the draft. Confirmation changes the
buffer's save target and marks it unsaved. It does **not** rename, create or
overwrite a disk file. A subsequent explicit `Save` writes the buffer to its
committed name. Executing a pane-tag command confirms a valid name draft