summaryrefslogtreecommitdiff
path: root/src/tutor.txt
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-08-27 22:30:11 -0300
committerGabriel Schneider <[email protected]>2026-08-27 22:34:41 -0300
commit337c2c66f40a08b67aa7ce4c73d01c335b9ae829 (patch)
treee46406f8847a42e4eb26e9a32af0617224ef06af /src/tutor.txt
parent98b62629795e24de19f535f1072b8a25dcf9f018 (diff)
downloadpardes-337c2c66f40a08b67aa7ce4c73d01c335b9ae829.tar.gz
pardes-337c2c66f40a08b67aa7ce4c73d01c335b9ae829.zip
tutor: half the length, and the parts people actually ask about
1297 lines to 498. The tutor had grown to the point where the things a newcomer needs first were buried in the middle of a helix reference, and two subsystems it never mentioned at all. REORDERED by what is most different from editors people arrive from, and each part now earns its place: 1 THE MOUSE acme's three buttons and the chords, trimmed 2 PANES NEW. Moving between them, in one place 3 THE TTY Ctrl-b, Shift-Esc, and what plain Esc does 4 DETACHED NEW. The core outliving the terminal showing it 5 THE KEYS the helix half, cut hard, practice blocks kept 6 THE REST PDFs, images, the language backend, scripting PANES was scattered across 3.12, part 2 and the summary; it is one section now, because "how do I get out of this pane" is the question that actually gets asked. Ctrl-w hjkl, Esc, Shift-Esc, Ctrl-o/Ctrl-i, Alt-n, Alt-c, and the three panes that have their own claim on Escape. THE TTY gains the rule the old text got wrong. It said Esc "goes to the program" in raw tty, full stop. It has not for a while: at a shell PROMPT plain Esc hops away like Shift-Esc, and only a program that has TAKEN the tty (vim, a pager) keeps it. That is `takesCommandLine` in pardes.zig, and it is the difference between the toggle feeling obvious and feeling arbitrary. DETACHED did not exist in the tutor at all. `--detach`, `--attach`, the Attach/Detach words and their chords, why the pane shells belong to the session and never stop, why N frontends share ONE screen at the smallest common grid, and that `--fs`/`--fs9` work in a daemon now. THE KEYS lost the most: thirteen subsections became six, roughly thirty practice blocks became six. What went is the enumeration a reference does better; what stayed is the handful of blocks that teach the one idea helix users do not arrive with -- motions SELECT, so `wd` is what `dw` was -- plus the count rule, which is the other thing that surprises. Part 6 documents `pty/`, `--fs9` and the `9p` word, none of which the tutor knew about. The first seven lines are byte-identical on purpose: test/snapshots/ tutor.golden pins them, and it regenerated unchanged. ALSO REGENERATED: test/snapshots/builtins.golden, which had been stale since the `9p` word was added a few changes ago -- one more builtin shifts every row of the `SPC ?` listing below it. Nothing was wrong with the code; the golden had simply not been updated with the feature. All 95 snapshot scripts pass.
Diffstat (limited to 'src/tutor.txt')
-rw-r--r--src/tutor.txt1489
1 files changed, 345 insertions, 1144 deletions
diff --git a/src/tutor.txt b/src/tutor.txt
index f75734e4..f712ab85 100644
--- a/src/tutor.txt
+++ b/src/tutor.txt
@@ -11,1287 +11,488 @@
= INTRODUCTION =
=================================================================
- Pardes is tmux + vi + acme, made from scratch. The foundation is
- the acme model: a pane is just text on screen. There is no separate
- "buffer" type — what you see is what you edit. Some panes happen to
- be live terminals (tty mode); most are text you can move a cursor
- over. Modal editing (helix-style) is layered on top of that.
+ A pane is just text on screen. There is no separate "buffer" type —
+ what you see is what you edit. Some panes happen to be live terminals;
+ most are text you move a cursor over. Modal editing is layered on top.
Three modes (the BOX at the pane's top-left corner shows which):
- NORMAL block cursor, keys move/edit. The box is BLANK: a pane
- at rest has nothing waiting to eat what you type.
+ NORMAL block cursor, keys move and edit. The box is BLANK.
^ INSERT keys type text at the cursor.
- $ TTY keys go straight to the shell. (terminals only)
+ $ TTY keys go straight to the shell. (terminals only)
- A bare `pardes` opens one shell already in TTY — there is nothing to
- edit yet. Give it a file or a directory and you start in NORMAL.
+ A bare `pardes` opens one shell already in TTY. Give it a file or a
+ directory and you start in NORMAL.
- This tutor is in FOUR parts, ordered by what's most different from
- editors you may know:
- PART 1 — the MOUSE. Acme's three buttons; nothing like Vim/Helix.
- PART 2 — the TTY. A terminal is just a pane; Ctrl-b (or Shift-Esc)
- drops into it.
- PART 3 — the KEYS. Helix-style modal (with the Pardes differences).
- PART 4 — the REST. Panes that are not text (PDFs, images), the
- language backend, and the chrome you can change.
+ SIX PARTS, ordered by what is most different from editors you know:
+ 1 — THE MOUSE. Acme's three buttons; nothing like vim.
+ 2 — PANES. Moving between them. Esc, Shift-Esc, Ctrl-w.
+ 3 — THE TTY. A terminal is a pane. Ctrl-b and Shift-Esc.
+ 4 — DETACHED. The core outliving the terminal showing it.
+ 5 — THE KEYS. Helix-style modal, and where it differs.
+ 6 — THE REST. PDFs, images, the language backend, scripting.
- PRACTICE BLOCKS (part 3): the "# keys:" line lists keystrokes
+ PRACTICE BLOCKS (part 5): the "# keys:" line lists keystrokes
(space-separated; esc/enter/bs are special, the rest type each char).
- The clean lines under "# before" are what you practice on; the lines
- under "# after" are what you should end up with. "# at: row,col"
- (right after # keys:) sets where the cursor starts. They are here to be
- TYPED, and that is all they are — nothing runs them. What pins the real
- behaviour is two suites. `zig build hxdiff` replays every case in
- test/hxcases against GOLDENS recorded from a real helix, and fails on
- any difference that is not written down as a waiver with a reason.
- `zig build hxparity` runs those cases, and a file of editing extras,
- twice inside pardes — once in a file pane, once in a shell — and
- demands the two agree.
+ The lines under "# before" are what you practice on; "# after" is what
+ you should end up with. They are here to be TYPED and nothing runs
+ them. What pins the real behaviour is `zig build hxdiff`, which replays
+ test/hxcases against goldens recorded from a real helix, and
+ `zig build hxparity`, which runs each case twice — once in a file pane,
+ once in a shell — and demands the two agree.
Hold j to reach part 1.
=================================================================
-= PART 1 — THE MOUSE (acme chording; the most different part) =
+= PART 1 — THE MOUSE (acme chording) =
=================================================================
- Acme's central idea: the THREE mouse buttons each ACT on text, and the
- keyboard mirrors them. Pardes inherits this. (Vim and Helix have almost
- none of it — their mouse is selection/scroll only.)
+ Three buttons, three verbs:
+ LEFT select, and focus the pane. Also pins the cursor.
+ MIDDLE EXECUTE the word or selection (a builtin, or a shell line).
+ RIGHT LOOK: open the file, directory or URL under the pointer.
- ┌─────────┬─────────┬─────────┐
- │ L │ M │ R │
- │ (1) │ (2) │ (3) │
- ├─────────┴─────────┴─────────┤
- │ │
- │ ( o ) │ the wheel scrolls the pane
- │ │
- └─────────────────────────────┘
+ CHORDS — hold one button and click another without letting go:
+ 1-2 (hold left, click middle) CUT the left selection
+ 1-3 (hold left, click right) PASTE over it
+ both, in one hold SNARF (copy)
+ 2-1 (hold middle, click left) execute the middle word WITH the
+ left selection as its argument
- L select a plain click also FOCUSES the pane and, outside tty
- mode, PINS the modal cursor where you click so you can
- edit there next. On a DOCUMENT it also drops you into
- normal mode; a terminal keeps the mode it had, so tty
- stays tty.
- M execute run the selected text: a builtin name runs it, anything
- else is SENT to the shell the pane runs. This is how you
- run a command you typed in a text mode.
- R look open the word under the cursor as a path: a directory
- opens/focuses a terminal there and ls's it; a file opens
- a file pane (scrolled to a ":line" suffix if present).
- A bare name is tried in THIS pane's directory first, then
- in the directories of the panes you have BEEN in, newest
- first and each directory tried once — a name none of them
- holds is what becomes a search.
+ Every tag with text leads with Save; a terminal also has Filter.
+ Images and PDFs show "New Del". The top bar is:
- WEB TOUCH (one finger): a tap is LOOK, the same action as R; a drag
- past a small movement threshold is natural scrolling.
- Once a gesture becomes a scroll it cannot also LOOK on
- release. The browser has no host filesystem or ptys:
- LOOK opens URLs or read-only Pardes .zig sources that
- were tracked or new/nonignored when the web build was made.
- The published launcher is a real Pardes terminal dump of
- Git's tracked-plus-new/nonignored source list: every listed
- path opens, and the opened source uses tree-sitter colors.
- A touch beginning on a tagline or pane separator instead
- latches a left-mouse gesture, so layout drags never scroll.
- Touch circles/trails and the click flash are the SDL
- build's debug overlay, drawn only while the Debug builtin
- is on. The browser draws no such thing.
+ New Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor
+ Debug Kill
- SELECT-THEN-ACT:
- - MIDDLE-drag over text selects AND runs it on release (one gesture);
- a no-drag middle click auto-expands to the word under the cursor.
- - or select with the keyboard (`v` chars / `x` lines), then press
- Tab to execute or Enter to look — the acme chords on the keyboard.
+ Reach it from the keyboard with `k` off the topmost tagline; `j` comes
+ back down.
- CHORDS (acme's held-button combos):
- 1-2 hold LEFT on a selection, tap MIDDLE: Cut it into the yank
- register (the snarf buffer).
- 1-3 hold LEFT, tap RIGHT: Paste the register over the selection,
- or splice it in at a bare click point. So 1-2 then 1-3 in the
- SAME hold = copy (Snarf): the text comes back, the register
- keeps it. After a chord the left release is inert.
- 2-1 hold a MIDDLE drag over a command, tap LEFT: the kept left
- selection rides along as the command's ARGUMENT. No selection
- in that pane? The pane the drag started in is asked first, then
- the active one, then the rest — a kept left selection or a v/x
- one, wherever it lives.
- 2-3 / 3-1 / 3-2 tapping the other button during a MIDDLE (execute)
- or RIGHT (look) drag CANCELS the gesture.
- In a TTY-mode shell 1-3 pastes into the program like a terminal:
- the click is forwarded first (if it listens for mouse) so the
- paste lands under it, then the register arrives — bracketed if
- the program asked for bracketed paste, raw otherwise.
- The selection a chord leaves behind is dismissed by the next left
- click (it doesn't stretch to the click).
+ KEYBOARD EQUIVALENTS, because the buttons are not the only way in:
+ Enter = LOOK (right button)
+ Tab = EXECUTE (middle button)
+ Both act on the selection when there is one. Neither is a way into TTY.
- THE TAG: each pane has a one-line tag: its directory or file path +
- builtins. (The mode is the box at the tag's left end, not a word in the
- tag.) Every pane shows "New" for an empty temporary file in its column.
- Anything holding TEXT leads with "Save". A file pane shows
- "Save New Del" and Save writes that file (an unsaved edit puts `*` after
- the filename); a pane with no file of its own — a terminal, an output
- buffer — needs the path, so "Save notes.txt" writes it under the pane's
- own directory and a bare "Save" arms a prompt already filled in with that
- directory. Del closes the window. Clicking a tag
- edits it in insert mode: type straight in, Enter looks / Tab executes
- body focuses that same tag in NORMAL mode, parked on the FIRST WORD of
- the tail rather than in the run of layout spaces before it — vim's
- command line with acme's words in it, and on a file that first word is
- "Save", so a bare `:` then Tab saves. `:w<Tab>` is w
- onto "Save", Tab to execute it, and you land back in the body where you
- left off (the chord keys are the same here as anywhere else; `i` if you
- would rather type a command than walk to one). A terminal shows
- "Save New Del Filter": Save writes its plaintext scrollback to the path
- you give and leaves it a terminal, and Filter starts on, is local to that
- terminal, and
- projects every rendered foreground and background ANSI, 256-colour and
- truecolour value through keys made from the current Pardes theme; run it
- to restore the program's original colours.
- Images and PDFs show the plain "New Del", because their bytes on disk
- already are exactly what they are. An image
- tag leads with "img" and a PDF's with the word "pdf", its page out of
- the count, and its three commands each preceded by its current setting
- (part 4.1) — all of it live chrome, like the path.
- In that normal mode h/j/k/l do NOT move inside the tag: a tagline is a
- place in the LAYOUT, so they focus the neighbouring window and land on
- ITS tagline, still in normal mode — you walk the taglines of the screen
- and never drop through a body. (Same moves as SPC w h/j/k/l and Ctrl-w
- h/j/k/l; nothing that way = you stay put.) The ARROWS are the in-tag
- motion, and w/b/e/0/$/^ still walk the tag's own words. Off the TOPMOST
- tagline k keeps going: above it is the top bar, which is a tagline too
- — the screen's own — and j comes back down.
- The path at the head of a tag is live chrome, so it cannot be edited —
- but it CAN be selected, by motion or by dragging across it: 0 then E
- selects exactly the path, `y` yanks it, Enter looks it. (`W` would drag
- the alignment spaces in with it.) Typing or backspacing
- with the cursor inside it does nothing; edits only ever reach the words
- you own, to the right of the path.
- "Delcol" still exists as a command: type it in
- a tag or body and execute it to close the whole column. A SEPARATE bar
- across the top of the screen holds the window-agnostic builtins:
- New Newcol Find Grep Help Tutor Dump NextColor Debug Kill
- — and one more, " Restore <path>", which appears the moment a Dump has
- written one.
- Middle-click "New" for an empty temporary file in this pane's column,
- "Newcol" for a new column, "Tutor" to spawn this tutor, "Kill" to
- quit. From the KEYBOARD the bar is `k` off the topmost
- tagline: it takes the cursor, h/l and the arrows move by character,
- w/b/e and 0/$ by word, Enter or Tab runs the word under the cursor the
- way a middle-click on it does (with one difference: the mouse can carry
- a selection kept elsewhere as the command's argument, and the keyboard
- cannot), j drops back onto the tagline
- below and Esc leaves. There is nothing to type up here — the bar is
- chrome, so it has no insert mode. Debug toggles the stats box in the
- top-right corner (and, where fingers exist, the touch circles and the
- LOOK flash). NextColor steps the theme RING one place — and the ring is
- 228 themes, not three: ours first ("helix", the default: a near-black
- page and chrome that barely lifts off it, copied from helix's own; then
- "dark"; then "acme", the acme-light yellow), then every theme helix and zed
- ship, generated out of vendor/themes when pardes is built and sorted by
- name. At 228 a step is a BROWSE and not a way to arrive: `Theme <name>`
- goes straight to one, and "ThemeSel" (SPC t t) lists all of them into a
- "+Themes" buffer whose rows ARE those commands — n/N to walk, Tab to
- wear the one you stopped on. The bar holds only what you reach for
- often — the rest of the builtins are words you execute and keys you
- press. Nearly every one has a KEY PATH under SPC (part 3.13): "Colors"
- (the global syntax/ANSI master switch) is SPC t c; a terminal's Filter
- setting stays remembered while Colors is off. The native GUI scene effects are
- SPC t r/R/g, panel transitions are SPC a s/z/d/a/v, and SPC ? lists the lot.
- Right-click a directory in any body to open a terminal there.
- SEARCH: `/` in normal mode types a pattern into that pane's own tag (it
- stays visible while you type; Esc abandons it). Enter searches the pane
- — a file's text, a shell's scrollback, anything — for the pattern, plain
- and case-insensitive, and writes one row per matching LINE into a
- "+Search" pane — the FIRST hit on that line, named as a location, with
- the line's own text after it — and then GOES to the first of those rows.
- That last part is nothing new to learn: it is the step `n` is and the
- look Enter is, run for you in the list that has just answered. A pattern
- that matched nothing opens its empty buffer and goes nowhere.
- That is an OUTPUT BUFFER: a file pane with no file behind it, so Save
- there always takes a path and asks for one when you do not give it —
- and writing it out leaves the buffer exactly where it was, still the
- list the next search refills. Everything else about it is an ordinary
- buffer you can read, edit, select and look in. The one that does become
- a file is "+New", the empty scratch, which is what it was opened for.
- It is not a document, though, and never takes a
- column of its own: it opens BELOW the pane that asked for it, in that
- pane's column, be that a file or a shell — and a file you then open from
- its rows goes where files go, not under the list. `n`/`N` carry on down
- those rows, and walking is ALL they do: a press moves the SELECTION to the
- next look-able thing and opens nothing, so you can step past nine hits
- to reach the tenth without opening the nine. Enter — the look chord —
- opens the one you stopped on. The walk is a RING over PANES and not
- over one buffer: the panes you have looked out of come first, most
- recent first, then the output buffers you have not, newest first, and
- only when there is neither does it step the pane in front of you — so
- n/N work on a shell that never had a search armed, and off the end
- they come round to the start. A Look from a result row may move focus
- into the source file; the result pane remains the walk's owner, so the
- next n/N returns there instead of starting from the file that opened.
- After the FIRST press `N` is `n`
- backwards exactly; the first one is not a step but an arrival, since
- from a cursor the walk has never stood on there is nothing yet to step
- back from.
- Right-clicking a word that names no file in ANY open pane's
- directory searches for it — acme's button 3 — except in tty mode, where
- a look that resolved nothing does nothing at all rather than searching.
- A hit in a file reads `path:LINE:COL-ENDCOL` and then the matching
- line's own text — the location is the leading word, and the path is
- spelled relative to the buffer's own directory. It is the ordinary look target
- carrying the SPAN that matched. A hit in a shell or an output buffer has no
- file to name, so it reads `@pN:LINE:COL-ENDCOL` — pane N, then the place in
- it. Looking either one goes there and SELECTS the span, which is why an
- Enter on a row n/N stepped to lands ON the hit rather than beside it.
- The range is part of the PATH syntax and not part of search: type one
- anywhere text lives and a look on it selects. `main.zig:412-418` is whole
- lines, `main.zig:412:9-21` is columns on one line, `main.zig:412:9-418:1`
- is the general form, and the shorter spellings still mean what they always
- did — `main.zig:100`, `main.zig:100:7`, `@p3:12`, all of them optional.
- FIND: the "Find" builtin (SPC f f) arms the same tag input, but Enter
- walks the pane's DIRECTORY instead of its text — `fd`, in-core — and writes
- one matching PATH per row into the same "+Search" buffer. Rows are look
- targets like any other, so n/N select them one at a time and Enter
- opens the one you meant; the match is on the name, plain and
- case-insensitive, and the walk skips the directories nobody means —
- .git, .jj, target, node_modules, .venv, __pycache__, .zig-cache and
- zig-out — and stops at 512 hits, sixteen levels down, or a hundred
- thousand directory entries, whichever comes first.
+=================================================================
+= PART 2 — PANES: MOVING BETWEEN THEM =
+=================================================================
- LAYOUT: columns split the screen; windows stack within a column. Panes
- abut with no wasted gap — a pane's own trailing edge (its last column, or
- last row above the next tag) IS the resize handle: hover it and a dashed
- line overlays that edge (keeping the underlying colors) to mark the drag.
- - drag a column's right edge to resize it against its neighbour
- - drag a window's bottom edge to resize it against the one below;
- either window may shrink to just its tagline (the tag row then IS
- the handle) — re-enlarging brings the body back intact
- - drag the move box (top-left of a pane; brighter when the pane is
- focused, and coloured by the theme) to MOVE a window between
- columns / reorder
- - the scrollbar is the gutter below the box: left-click scrolls UP
- to that point, right-click scrolls DOWN
- - the FIRST document you open — a file, an image, a PDF, this tutor —
- takes a new leftmost column of its own, paid for only by the column
- you opened it from; every unrelated column keeps its exact rectangle.
- Every later document splits below a doc
- already open, so docs share that column
- - closing a window (Del, or its shell exiting) hands focus back to the
- window you were in before it, not to whichever one comes first
+ Panes live in columns. Everything here works in any mode, because
+ getting OUT of a pane must work from inside a pane that owns its keys.
- (Mouse actions are hard to unit-test from text; native gestures are
- covered by the e2e suite. Browser touch and embedded-source LOOK are
- driven through real Chromium input by `zig build web-snap`.)
+ FOCUS A NEIGHBOUR
+ Ctrl-w h/j/k/l focus the pane left / down / up / right
+ SPC w h/j/k/l the same, in body normal mode only
+ Use Ctrl-w in a terminal: there SPC belongs to the shell.
+ GO BACK
+ Esc hop to the pane you were in BEFORE this one. Held down
+ it alternates between two. This is the `Last` builtin,
+ also SPC j j.
+ Ctrl-o walk the jump history BACK (the `Back` builtin)
+ Ctrl-i walk it FORWARD (`Forward`; SPC j l shows
+ the stack as a buffer)
+ Ctrl-i and Tab are the same byte on an old terminal. Where they are,
+ Tab keeps meaning execute and Ctrl-i does nothing — the right way
+ round, since Tab-executes is the older and more used of the two.
-=================================================================
-= PART 2 — THE TTY (a terminal is just a pane) =
-=================================================================
+ WHEN Esc MEANS SOMETHING ELSE
+ Three panes have their own claim on Escape, so there is a second
+ spelling that always leaves:
- This is the headline difference from Vim/Helix: there is no "open a
- terminal in a split" that's separate from "edit a file in a split".
- A TERMINAL IS A PANE. The same modal keys that edit a file navigate
- the terminal's screen, and dropping into tty REUSES the shell's own
- prompt model rather than layering an editor cursor on top.
+ Shift-Esc leave this pane, whatever Escape means inside it
- On a terminal pane:
- NORMAL ( ) the PROMPTS are gone — a clean acme-style page — but the
- command you typed at each one stays, pulled over to the
- left edge, because that is the part worth reading. A
- prompt you never typed at leaves a blank row behind. You
- navigate the
- page with the same h/j/k/l/w/b/e as a file.
- INSERT (^) the same page; keys type an insertion overlay (the
- command you're composing).
- TTY ($) the REAL shell — prompts back, and keys go straight to
- the pty as terminal input.
-
- ESC: insert -> normal; from body NORMAL it hops to the pane you
- were in before this one, whichever it was (the same Last as
- SPC j j) — so held down it alternates between two panes.
- In raw TTY it still goes to the program.
- Ctrl-b: toggles TTY on a terminal, and is the only way back OUT of it.
- SHIFT-ESC gets you IN, and once in TTY it does what ESC does in
- normal mode — hops away, leaving this pane in TTY so coming
- back lands you in the program you left.
- Use `pardes --tty-toggle=g` to make Ctrl-g the toggle instead —
- any letter but `c`, which stays SIGINT. Entering is tty-native:
- if the shell is at a prompt and your modal cursor sits on the
- input line, it first moves the shell's REAL cursor to that spot,
- counting back the prompt columns that were hidden from you,
- via the shell's OSC 133 semantic prompt (ghostty promptClickMove;
- our rc opts in with cl=line). The shell moves its own cursor with
- arrow keys it understands — Pardes doesn't fake one on top.
+ in INSERT Esc returns to normal. Press it again to hop.
+ in a PDF Esc cancels the selection and the search highlights
+ and stays in the document. Shift-Esc hops out.
+ in raw TTY Esc goes to the program — vim gets its Escape.
+ Shift-Esc hops out. But see part 3: at a shell
+ PROMPT, plain Esc hops too.
- ENTER / TAB (in normal) are NOT a way into tty — they're the acme mouse
- chords on the keyboard: Enter = "look" (open the path under the cursor),
- Tab = "execute". Both act on the selection if one is active.
+ Shift-Esc needs a terminal that reports modifiers on Escape (the kitty
+ keyboard protocol). Where the host does not, it arrives as a plain
+ Escape and means whatever Escape means in that pane.
- So the flow is: navigate the hidden-prompt page in normal, hit the tty
- toggle where you want to keep typing, and you're IN the live shell at
- that spot. No separate "terminal mode cursor" to reconcile.
+ MAKE AND MOVE PANES
+ Alt-n new terminal below the active one
+ Alt-c move the active pane into a fresh column — any pane, not
+ just a terminal. A no-op if it is alone in its column,
+ or if the sixth column already exists.
+ New Newcol in the top bar: a pane, or a pane in a new column
+ Joincol delete this column, move its panes to the one right
+ Del in a pane's own tag: close it
- (The cursor positioning is enterTty's promptClickMove; it needs a live
- shell at a prompt. Mouse/tty behavior is exercised by the e2e suite.)
+ A new file opens in a new COLUMN only if both panes would still get
+ 100 columns of width. Otherwise it stacks in the one you are in.
=================================================================
-= PART 3 — THE KEYS (helix-style modal, Pardes differences) =
+= PART 3 — THE TTY (a terminal is just a pane) =
=================================================================
- Same core as Helix: a block cursor you move with h/j/k/l, motions
- w/b/e, insert with i/a/o, and a SELECTION every edit acts on. Two
- differential suites — `zig build hxdiff`, which replays these keys
- against goldens recorded from a real helix, and `zig build hxparity`,
- which runs them twice inside pardes and demands a file pane and a shell
- agree — fail the build on any difference nobody has written a waiver
- for. So where this file disagrees with helix's own
- manual, helix is right and this file is the bug. The deliberate
- divergences:
+ There is no "open a terminal in a split" separate from "edit a file in
+ a split". A TERMINAL IS A PANE. The same modal keys that edit a file
+ navigate the terminal's screen.
- - Selection is LINE-first: `x` grows a line selection downward, and
- an edit with nothing selected acts on the line (or the character)
- the cursor is on. `v` is the CHARACTER range when you want one.
- - NO verb+noun (Vim's dw, cw) — because the motion has already made
- the selection. A traversal motion SELECTS what it crossed (3.3), so
- `wd` is what `dw` was; `miw` then `d` deletes a word from inside it,
- and `x` then `d` deletes whole lines.
- - A plain ESC never reaches tty. From a BODY in normal mode it hops
- to the pane you were in before this one; everywhere else it leaves
- insert, or abandons a leader path, a tag, an armed input. Dropping
- a terminal into the live shell is the tty toggle (Ctrl-b by
- default, or Shift-Esc; see Part 2).
- - Enter / Tab in normal mirror the mouse: Enter = look (open the path
- under the cursor), Tab = execute. `:` runs a command from the tag
- (see Part 1). `u` undo, `U` redo.
- - `/` is a plain case-insensitive SUBSTRING search (Part 1), not
- helix's regex one. There IS a regex engine and it lives on `s` and
- `S` alone (3.7).
- - Alt-c moves this pane to a fresh column instead of helix's
- change-noyank, and Ctrl-b pages up in a document but toggles tty on
- a terminal. Those two are written down as waivers, not accidents.
- - Editing a file pane MUTATES real content; a terminal pane yanks
- rendered text and pastes it as an insertion run (shell output
- can't be deleted, only pasted text can).
+ On a terminal pane:
+ NORMAL ( ) the PROMPTS are gone — a clean acme page — but the
+ command you typed at each one stays, pulled to the left
+ edge, because that is the part worth reading. Navigate
+ with the same h/j/k/l/w/b/e as a file.
+ INSERT (^) the same page; keys type an insertion overlay.
+ TTY ($) the REAL shell. Prompts back, keys straight to the pty.
- PRACTICE: run the keys on the "# before" lines; you should get the
- "# after" lines.
+ THE TOGGLE
+ Ctrl-b in and out of raw TTY, on a terminal pane
+ Shift-Esc the same toggle, spelled for hosts that report modifiers
+ on Escape
+ `pardes --tty-toggle=g` makes it Ctrl-g instead — any letter but `c`,
+ which stays SIGINT.
------------------------------------------------------------------
-= 3.1 MOVING THE CURSOR (h j k l), AND COUNTS =
------------------------------------------------------------------
+ Entering TTY is tty-NATIVE, and this is the part worth understanding.
+ If the shell is at a prompt and your modal cursor sits on the input
+ line, pardes first moves the shell's REAL cursor to that spot, counting
+ back the prompt columns that were hidden from you. It does that with
+ arrow keys the shell already understands, through the shell's own OSC
+ 133 semantic prompt marks — it does not fake a cursor on top. So you
+ navigate the clean page, hit the toggle where you want to keep typing,
+ and you are IN the live shell at that spot.
- k * h = left, l = right
- h l * j = down, k = up (also: arrow keys)
- j
+ LEAVING
+ Ctrl-b back to normal on this pane
+ Shift-Esc hop AWAY, leaving this pane in TTY — so coming back
+ lands you in the program you left
+ Esc goes to the program... unless the leaf process is a
+ SHELL sitting at its prompt, in which case it hops away
+ exactly like Shift-Esc
- The cursor sits ON a character (block). Motions only move.
+ That last rule is the one people ask about. A shell prompt is a pane
+ you can leave, so plain Esc leaves it; a full-screen program (vim, a
+ pager, an agent) has taken the tty, so Esc belongs to the program and
+ you need Shift-Esc. Pardes knows which by asking whether the pane's
+ leaf process is still the prompt it forked.
-# keys: l l l
-# before
-abcdef
-# after
-abcdef
+ PASTING INTO THE PROGRAM
+ Ctrl-V type the DEFAULT register — what `y` put there
+ Ctrl-Shift-V ask the SYSTEM clipboard
+ SPC p and the mouse chords cannot reach here: the pty owns every
+ keystroke and every button.
- A number typed FIRST is a count. Not everything takes one, and the set
- that does is worth knowing: the motions (h/j/k/l, w/b/e, W/B/E), the
- four f/F/t/T and the `Alt-.` that repeats them, `gg`/`gj`/`gk`/`g|`,
- `x`, `o` and `O`, `>` and `<`, `p` and `P`, Ctrl-a and Ctrl-x,
- `]p`/`[p` and `]space`/`[space`, and the three cursor-list keys `C`,
- `Alt-C` and `)`/`(`. Everywhere else the
- number is swallowed — `3d` deletes once, `3i` types once, `3ge` goes to
- the last line like `ge`. `0` is still
- line-start and never the start of a count, and Ctrl-d/u/f/b ignore one
- on purpose: a page is a page.
+ `Filter` in a terminal's tag toggles a pane-local, theme-keyed palette.
-# keys: 3 l i Z esc
-# before
-abcdef
-# after
-abcZdef
+=================================================================
+= PART 4 — DETACHED SESSIONS (the core outlives the terminal) =
+=================================================================
------------------------------------------------------------------
-= 3.2 ENTERING INSERT: i a A I o O =
------------------------------------------------------------------
+ A pardes session is a core — the text, the undo history, the layout,
+ the pane shells — and a frontend that draws it. Normally they are one
+ process. They do not have to be.
- `i` insert at cursor. `a` insert AFTER the cursor.
- `A` insert at end of line. `I` insert at first non-blank.
- `o` open line BELOW + insert. `O` open line ABOVE + insert.
- (All match Vim and Helix.)
+ STARTING ONE
+ pardes --detach a session named by this process's pid
+ pardes --detach=work ...named `work`
+ pardes --attach become a frontend of the one session there is
+ pardes --attach=work ...of the session called `work`
+ pardes-gui --attach=work an SDL window is a frontend too
-# keys: i X esc
-# before
-bcdef
-# after
-Xbcdef
+ And from inside a running editor, as ordinary acme words — type one in
+ a tag and execute it, or press its chord:
- Cursor on 'b' (col 0). `i` inserts before 'b'.
+ Attach hand this window to the session there is (SPC s a)
+ Attach work ...to `work`
+ Detach leave the session, and leave it running (SPC s D)
-# keys: a Z esc
-# before
-abc
-# after
-aZbc
+ WHAT MAKES IT DIFFERENT FROM tmux
+ The pane shells belong to the SESSION, not to the frontend. Attach,
+ detach, kill the terminal, attach from another one, and the build that
+ was running in pane 3 is still running and has been scrolling into the
+ core the whole time. Nothing is replayed to you; it never stopped.
- Cursor on 'a' (col 0). `a` inserts after 'a'.
+ `Attach` switches IN PLACE. The window, the terminal and the process
+ stay; what changes is where the state lives. Only on a successful
+ handshake does the frontend give up its own core — so a failed attach
+ costs you nothing.
-# keys: A Z esc
-# before
-abc
-# after
-abcZ
+ `Detach` is the smaller half: only the frontend that ran it leaves.
+ The session, its shells and every other attached frontend are
+ untouched, so leaving is a SUCCESS — the terminal prints where to come
+ back to and exits 0. In a session with nothing to detach from it says
+ so on the message row and does nothing.
- `A` jumps to end then inserts — appends 'Z'.
+ MORE THAN ONE FRONTEND
+ N frontends attached to one session all see the SAME screen, at the
+ smallest common grid — `screen -x`, not N sessions. Two windows of
+ different sizes converge on the smaller and the larger letterboxes.
-# keys: I Z esc
-# before
- abc
-# after
- Zabc
+ WHAT A DAEMON CAN ALSO DO
+ A detached session serves acme's control filesystem like any other:
- `I` goes to the first non-blank ('a'), inserts before it.
+ pardes --detach=work --fs the tree under $XDG_RUNTIME_DIR
+ pardes --detach=work --fs9 the same tree, as 9P on a unix socket
-# keys: o line2 esc
-# before
-line1
-# after
-line1
-line2
+ Either, both or neither. That is what makes a daemon scriptable while
+ nobody is looking at it — see part 6.
- `o` makes a blank line below, enters insert, "line2" typed, Esc.
+ The socket lives in $XDG_RUNTIME_DIR (else ~/.local/state/pardes),
+ created 0700, never /tmp: it carries keystrokes into a live editor.
-# keys: O top esc
-# before
-bot
-# after
-top
-bot
+=================================================================
+= PART 5 — THE KEYS (helix-style modal) =
+=================================================================
+
+ Same core as helix: a block cursor you move with h/j/k/l, motions that
+ SELECT what they cross, and an edit that acts on the selection. There
+ is no verb+noun — the motion already selected, so `wd` is what `dw`
+ was in vim.
-----------------------------------------------------------------
-= 3.3 WORD MOTIONS: w b e (W B E long) =
+= 5.1 MOTION AND COUNTS =
-----------------------------------------------------------------
- `w` next word start, `b` prev word start, `e` next word END.
- W/B/E treat punctuation as part of the word. Same letters as Vim.
-
- NOT the same MEANING, though, and this is the one thing to unlearn:
- a word motion in helix SELECTS what it crossed. `w` from 'f' does not
- just park on 'b' — it leaves "foo " selected with the cursor at its
- end. That is why d needs no motion after it (3.6): the motion already
- made the selection.
-
-# keys: w d
-# before
-foo bar
-# after
-bar
-
- `w` from 'f'(col0) selects "foo " up to 'b'(col4); `d` deletes it.
-
-# keys: e d
-# before
-foo bar
-# after
- bar
+ k h left, l right, j down, k up (also arrows)
+ h l w/b/e word forward/back/end (W/B/E long)
+ j 0 line start, $ end, ^ first non-blank
+ gg first line, ge START of the last line
+ f/F/t/T find a character forward/back
- `e` selects to the END of "foo" and no further, so the space stays.
+ Bare G does NOTHING. `ge` is the start of the last line.
-# keys: b d
-# at: 0,4
+# keys: l l l
# before
-foo bar
+abcdef
# after
-bar
-
- Cursor on 'b'(col4, "bar"). `b` selects back to 'f'(col0).
+abcdef
- The consequence to remember: `i` inserts at the START of whatever is
- selected, not where the cursor sits. After `w` on "foo bar", `i`
- types at column 0. `;` collapses the selection onto the cursor first,
- so `w;i` is the vim reading of `wi`.
+ A number typed FIRST is a count, and only some keys take one: the
+ motions, f/F/t/T and the `Alt-.` that repeats them, gg/gj/gk/g|, `x`,
+ `o`/`O`, `>`/`<`, `p`/`P`, Ctrl-a/Ctrl-x, ]p/[p and ]space/[space, and
+ the cursor-list keys C, Alt-C and )/(. Everywhere else it is swallowed:
+ `3d` deletes once, `3i` types once. `0` is always line-start and never
+ the start of a count. Ctrl-d/u/f/b ignore counts: a page is a page.
-# keys: w ; i Z esc
+# keys: 3 l i Z esc
# before
-foo bar
+abcdef
# after
-fooZ bar
-
+abcZdef
-----------------------------------------------------------------
-= 3.4 LINE BOUNDS AND GOTO: 0 $ ^ and the g prefix =
+= 5.2 ENTERING INSERT =
-----------------------------------------------------------------
- `0` start of line, `$` end, `^` first non-blank. These three MOVE
- without selecting, unlike the word motions above — so `$i` really
- does insert at the end of the line.
-
-# keys: $ i Z esc
-# before
-abcde
-# after
-abcdZe
-
- `$` to last char 'e', insert before it. (Cursor ON a char, so "end" =
- last char, not past it.)
+ `i` at the cursor. `a` after it. `I` first non-blank. `A` end of
+ line. `o` open below. `O` open above. Esc returns to normal.
-# keys: 0 i Z esc
+# keys: i X esc
# before
-abcde
+abc
# after
-Zabcde
+Xabc
-# keys: ^ i Z esc
+# keys: o line2 esc
# before
- abcde
+line1
# after
- Zabcde
-
- `g` is a PREFIX, and it is helix's g rather than vim's:
-
- gg first line ge LAST line (what vim spells G)
- Ngg line N Ng| column N
- gh line start gl line end gs first non-blank
- gj VISUAL line down gk VISUAL line up
- gt the view's top row gc its middle gb its bottom
- (top and bottom are scrolloff-clamped: three rows in, so they
- land where the cursor could have scrolled to anyway)
-
- `G` ALONE DOES NOTHING. helix's goto_line only acts with a count, so
- `12G` is line 12 and a bare `G` is a keystroke that went nowhere —
- `ge` is the key that takes you to the last line — its START, the way
- `gg` takes you to the first line's.
-
- `gj`/`gk` are the VISUAL pair: with soft wrap on (`SPC t w`, part 4.1,
- on to start) one long line is drawn as several rows, and these two walk
- those rows — the automatic breaks, not the newlines — keeping the column
- they had inside the row. Plain `j`/`k` stay whole FILE lines, so on a
- wrapped paragraph `j` jumps past every row of it and `gj` steps one. With
- wrap off a line is one row and the two pairs are the same key.
-
- Five more gotos live under the same prefix — gd gD gy gi gr — and
- they belong to the language backend, in part 4.2.
-
+line1
+line2
-----------------------------------------------------------------
-= 3.5 FINDING A CHARACTER: f F t T =
+= 5.3 MOTIONS SELECT =
-----------------------------------------------------------------
- `f<char>` extends the selection forward THROUGH the next <char> on
- this line, `F<char>` backwards. `t` and `T` are the same two but stop
- one short of it. A count takes the Nth — `2fo` is the second `o`.
- `Alt-.` repeats whichever of the four you used last.
+ w/b/e and f/F/t/T leave a SELECTION behind them. So `i` after a motion
+ types at the selection's START, not where the cursor stopped. `;`
+ collapses a selection to a single cursor first.
- They select, the way w/b/e do, so d is the natural next key: `fx` and
- then `d` deletes everything up to and including the next x.
-
-# keys: f d d
-# before
-abcdef
-# after
-ef
-
- `fd` selects "abcd"; `d` deletes it.
-
-# keys: t d d
+# keys: w ; i Z esc
# before
-abcdef
+one two
# after
-def
-
- `td` stops one short, so only "abc" goes.
-
+one Ztwo
-----------------------------------------------------------------
-= 3.6 SELECTION + EDIT: x v d c y p, and the rest =
+= 5.4 SELECT AND EDIT =
-----------------------------------------------------------------
- The Pardes difference is LINE-first selection: `x` grows a line
- selection downward; d/c/y act on it. `v` is still available for a
- character range when you need one.
-
- `x` start/extend a line selection
- `X` stretch the selection you have out to whole lines
- `Alt-x` the opposite — shrink it back inside them
- `v` character-range select mode; motions extend it
- `;` collapse the selection onto the cursor; `Alt-;` flip its ends
- `%` select the whole file
- `d` delete the selected lines (yanked)
- `Alt-d` delete them WITHOUT yanking
- `c` clear the line + insert (change)
- `y` yank the selection — and with nothing selected the selection is
- the CHARACTER under the cursor, not the line, so `x` first if a
- line is what you meant
- `p` `P` paste the yank after / before. A LINE yank comes back as a
- whole line below or above; a character yank splices in beside
- the cursor
- `R` replace the selection with the yank
- `r<char>` overwrite every character of the selection with <char>
-
-# keys: x d
-# at: 1,0
-# before
-keep
-gone
-# after
-keep
+ x select the LINE (again: extend by one more)
+ v character-wise select, then move
+ d delete the selection c change it y yank it
+ p / P paste after / before
+ u undo U redo
+ > < indent / outdent Ctrl-a / Ctrl-x increment / decrement
- Cursor on "gone" (row 1). `x` selects it, `d` deletes it.
-
-# keys: x x d
-# at: 1,0
-# before
-a
-b
-c
-# after
-a
-
- `x` selects "b", `x` extends to "c", `d` removes both.
-
-# keys: x y j p
-# before
-orig
-dupe
-# after
-orig
-dupe
-orig
-
- `x` selects "orig", `y` yanks it, `j` to "dupe", `p` pastes below.
+ Selection is LINE-first here — `x` — with `v` for characters. That is
+ the main divergence from helix.
# keys: x c typed esc
# before
-old
+replace me
# after
typed
- `x` selects "old", `c` clears it to an empty line + insert, type.
-
-# keys: c Q esc
-# at: 0,1
-# before
-ab
-# after
-aQ
-
- No selection: cursor on 'b'(col1). `c` deletes 'b' + insert; type 'Q'.
-
- And the ones that rewrite a selection where it stands:
-
- `~` toggle case `` ` `` lowercase ``Alt-` `` uppercase
- `J` join this line with the next, on one space
- `>` `<` indent / unindent by four spaces (a count = that many)
- `Ctrl-a` `Ctrl-x` add to / subtract from the SELECTION read as a
- decimal integer. With nothing selected the selection is
- one character, so `41` with the cursor on the `4` becomes
- `51` — select the whole number first if you meant 42
- `Ctrl-c` comment or uncomment every line the selection touches.
- The token comes from the file's EXTENSION: `//` for .zig
- and .c, `#` for .py and .sh, `--` for .lua, `;` for .el,
- `%` for .tex and .erl, `!` for fortran, `"` for .vim —
- and `#` for any extension the table does not name, which
- includes having none. In raw tty mode Ctrl-c is still the
- shell's SIGINT.
- `=` ask the language backend to format the selection (part 4.2)
-
-# keys: x ~
-# before
-abc
-# after
-ABC
-
-# keys: J
-# before
-one
-two
-# after
-one two
-
-# keys: x >
-# before
-abc
-# after
- abc
-
-
------------------------------------------------------------------
-= 3.7 MORE THAN ONE CURSOR: s S C , ) ( _ =
------------------------------------------------------------------
-
- There IS multi-cursor, and it is helix's: a selection is a LIST of
- ranges with one PRIMARY among them, and every ordinary key is
- replayed once per range — type in insert and you type in all of them.
- Sixty-four ranges is the ceiling; matches past it are dropped.
-
- The two keys that make a LIST out of one range are regex:
-
- `s` keep every match inside each selection, as its own cursor
- `S` keep the pieces BETWEEN the matches instead
-
- Both arm the pane's tag the way `/` does, and both preview LIVE: the
- selections redraw on every character you type. A pattern that does not
- compile yet falls back to the selection you had BEFORE you pressed `s`
- rather than clearing everything, which is what makes typing one
- character at a time bearable — every unfinished prefix of a pattern is
- one of those. Enter commits, Esc puts back exactly what you had. A pattern
- with no uppercase in it matches case-blind, which is helix's smart
- case. Two things differ from helix's regex: `.` matches a newline here
- like any other byte, and `^`/`$` assert at the scanner's position
- rather than at a line boundary.
-
- The keys that then work on the LIST rather than on the text:
-
- `C` copy the primary selection down a line; `Alt-C` up
- `,` keep only the primary; `Alt-,` drop it, promote the next
- `)` `(` rotate which one is primary, forward / back
- `Alt-s` split every selection into one range per line
- `Alt--` merge them all into one span
- `Alt-_` merge only the ones that touch
- `_` trim the whitespace off each; empty ones vanish
-
- `SPC y` joins every cursor's text for the system clipboard and
- `SPC Y` takes the primary's alone (3.13).
-
- (No practice blocks: the "# keys:" notation has one cursor in it.)
-
-
------------------------------------------------------------------
-= 3.8 PAIRS AND TEXTOBJECTS: the m prefix =
------------------------------------------------------------------
-
- `mm` jump to the bracket matching the one under the cursor
- `mi<obj>` select INSIDE a textobject
- `ma<obj>` select AROUND it — delimiters included
- `ms<char>` surround the selection with <char> and its partner
- `mr<a><b>` replace the enclosing <a> pair with <b>'s
- `md<char>` delete the enclosing <char> pair
-
- The objects are `w` a word, `W` a long word, `p` a paragraph, and the
- pairs `( ) [ ] { } < >` with the quotes `'` `"` and the backquote.
- Quotes are LINE-SCOPED — a string does not span lines here, so
- neither does the object. helix's tree-sitter objects (a function, a
- class, an argument) are not in this set. For SURROUNDING, any
- character at all is its own pair: `msx` wraps the selection in x's.
-
- `miw` and then `d` is how you delete a word without a verb+noun
- grammar.
-
-
------------------------------------------------------------------
-= 3.9 ] AND [ : STEPPING BY THING =
------------------------------------------------------------------
-
- `]p` `[p` next / previous paragraph (blank lines delimit one)
- `]space` add a blank line below; `[space` above (a count = N)
- `]d` `[d` next / previous diagnostic — and if no list is up yet,
- asking the language backend for one is part of the press
- `]D` `[D` the last / the first of them
-
-
------------------------------------------------------------------
-= 3.10 PIPING A SELECTION: | =
------------------------------------------------------------------
-
- `|` in a file body arms the pane's tag with a bare "|" and takes a
- command line. Enter runs it under `/bin/sh -c` once per selection:
- the selection's bytes go in on stdin, and its stdout replaces them.
- Every cursor is filtered in the same pass, and the whole thing is ONE
- undo. `%` then `| sort` sorts a file.
-
- A pane whose BYTES ARE ITS OWN, and only that: a real file, or the
- scratch that is on its way to being one. So `|` is inert in a terminal
- (shell output cannot be rewritten) and in a rendered output buffer like
- "+Search", whose next refill would discard the filtered rows anyway, and
- in both the tag stays as it was.
-
- Not to be confused with EXECUTING a word, which sends it to the
- pane's own shell and leaves the text alone. This one is a filter, and
- what it returns lands back in the buffer.
-
-
------------------------------------------------------------------
-= 3.11 INSERT MODE ITSELF =
------------------------------------------------------------------
-
- Backspace, Delete, Enter and Tab are what those keys ARE, not
- bindings — Enter carries the previous line's indentation down with
- it. The rest is helix's:
-
- Ctrl-h / Ctrl-j / Ctrl-d Backspace / Enter / Delete, spelled out
- Ctrl-w, Alt-Backspace delete the word behind the cursor
- Alt-d, Alt-Delete delete the word in front of it
- Ctrl-u kill back to the start of the line
- Ctrl-k kill forward to the end of it
-
- Ctrl-w is the WINDOW prefix in normal and tty mode; insert mode wins
- it, which is helix's own arrangement — so a tag being typed into
- swallows it.
-
- TAB has one extra job: pressed straight after a `.` in a source file
- the language backend speaks, it asks what could go there (part 4.2).
- Everywhere else — and when the answer comes back empty — it indents
- to the next four-column stop.
-
-
-----------------------------------------------------------------
-= 3.12 VIEWPORT + PANES =
+= 5.5 THE REST, IN ONE PLACE =
-----------------------------------------------------------------
- zt / zz / zb scroll so the cursor is at top/center/bottom
- (`zc` is `zz` spelled the other way)
- zj / zk scroll the view one line, cursor pushed along
- Ctrl-d / Ctrl-u half-page down / up
- Ctrl-f full page down. (Ctrl-b pages up on a file pane;
- on a terminal it is the default tty toggle. If you
- start with --tty-toggle=g, Ctrl-g takes that role.)
- Ctrl-o / Ctrl-i walk the jump history back / forward — the same
- two builtins as SPC j o and SPC j i, and SPC j l
- shows the stack itself as a buffer. (Ctrl-i and Tab
- are the same byte on an old terminal; where that is
- so, Tab keeps meaning execute.)
- Ctrl-w h/j/k/l focus the pane left/down/up/right (SPC w h/j/k/l
- does the same; Ctrl-w also reaches a tty pane,
- where SPC belongs to the shell)
- Esc hop to the pane you were in before this one, so
- held down it alternates between two (body normal
- mode; the same builtin as SPC j j). A PDF pane is the
- one exception — there Esc cancels the selection and
- the search highlights and stays in the document, and
- Shift-Esc is the hop out (part 4.1)
- Alt-n new terminal below the active one
- Alt-c move the active pane into a fresh column — any pane,
- not just a terminal, and a no-op if it is alone in
- its column or the sixth column already exists
-
- (No practice blocks: these are viewport/layout, not text edits.)
+ s / S regex, one cursor per match, previewing as you type.
+ C , ( ) Alt-s Alt-- Alt-_ _ work the resulting LIST.
+ m i / m a textobjects: w W p, the bracket pairs, the three quotes
+ m s/r/d surround add / replace / delete; mm jump to the match
+ ] [ step by paragraph, blank line, diagnostic
+ | filter every selection through /bin/sh -c (savable file
+ panes only)
+ : the tag as a command line
+ / case-insensitive SUBSTRING search, one hit per line — not
+ a regex. The regex lives on s and S.
+ n / N select the next/previous LOOK-able text, across panes, as
+ a ring. Enter opens what you land on.
+ VIEWPORT
+ zt zz zb scroll so the cursor is at top / center / bottom
+ zj zk scroll one line, cursor pushed along
+ Ctrl-d/u half page down / up
+ Ctrl-f full page down. Ctrl-b pages up on a FILE pane; on a
+ terminal it is the tty toggle (part 3).
-----------------------------------------------------------------
-= 3.13 SPC — THE LEADER =
+= 5.6 SPC — THE LEADER =
-----------------------------------------------------------------
- Nearly every builtin has a NAME you can execute anywhere text lives,
- and a KEY PATH you can press. SPC in body normal mode starts the
- path; the keys you have typed so far show on the active pane's
- transient body/message row until it fires. Esc abandons it — so does any
- key that leads nowhere, rather than leaving the next keystroke armed.
-
- The groups are shared first letters and nothing cleverer: f files,
- h docs, c columns, t toggles, a animations, s session, j jumps,
- l language, w windows.
-
- SPC ? Help: every builtin and the keys that run it
- SPC k Kill (quit) SPC d Del (close this pane)
-
- SPC f s Save SPC f n New (empty temp file)
- SPC f f Find (file NAMES) SPC f g Grep (their CONTENTS)
- SPC f c Config: where the startup file is read from (4.3)
-
- SPC h t Tutor (this file)
- SPC c n / c d Newcol / Delcol
-
- SPC t d Debug SPC t c Colors (syntax/ansi recolor)
- SPC t n NextColor SPC t t ThemeSel (the list of 228)
- SPC t r/R/g Crt / Ripple / Glitch (gui and macOS only)
- SPC t f FontSel (gui and macOS only)
- SPC a s/z/d/a/v PanelSlide / PanelZoom / PanelDissolve / PanelAscii /
- PanelVertical
- SPC a e/f/w PanelEdges / PanelFall / PanelWave
- SPC a c/r/t PanelCurtain / PanelScramble / PanelType — glyphs
- marching in, churning into place, and typed in
- reading order
- (native tty, SDL GUI, and macOS; press again to turn off)
- SPC t w Wrap: soft line breaks in a file pane, ON to start
- with — so this is the switch that lets a long line
- run off the edge again, hscroll and all. A wrapped
- row ends in "↩", in the chrome's colour, because a
- break is the one thing about it you cannot see
- SPC t b Tagbottom: taglines under their panes, not over
- SPC t p/l/a Petscii / Palette / Ascii — an image pane's
- renderer (4.1)
- SPC t i/s/z PdfTint / PdfSections / PdfFit — a PDF's (4.1)
-
- SPC y / SPC Y the selection to the SYSTEM clipboard (every
- cursor's text joined, or the primary's alone)
- SPC p / SPC P paste the system clipboard after / before the
- selection; SPC R replaces the selection with it
-
- SPC s d / s r Dump / Restore the session
- SPC w h/j/k/l Left/Down/Up/Right: focus the pane that way
- SPC j o / j i Back / Forward: walk the jump history
- SPC j j Last: the pane you were in before this one — what
- body-normal ESC runs, so it alternates
- SPC j l Jumplist: that same stack, as a buffer you can click
-
- SPC l ... the language group — part 4.2 has all ten
+ Nearly every builtin has a NAME you can execute anywhere text lives and
+ a KEY PATH you can press. SPC in body normal mode starts the path; what
+ you have typed shows on the pane's message row until it fires. Esc
+ abandons it, and so does any key that leads nowhere.
- Those five clipboard words are helix's own letters, and the only
- words in pardes that touch the desktop's clipboard at all: ordinary
- y d c p P R and the 1-2 / 1-3 chords stay in pardes' own register, so
- deleting a character can never throw away what you copied from a
- browser. In a terminal the copy goes out as OSC 52 and the paste asks
- for it back the same way — plenty of terminals refuse that read, so
- there SPC y works and SPC p may honestly do nothing.
-
- A handful of builtins have no key path at all. Three of them take a
- NAME, and a key path can never carry one: `Theme <name>`, `Font <name>` and
- `Shell <name>` — the last being what the NEXT terminal you open will
- run (fish, until you say otherwise; the ones already open keep what
- they have). The other two are Look and Exec, which already have two
- keys and two buttons between them. All five are words: write them
- anywhere and execute them.
-
- `?` works at ANY depth: SPC ? lists everything, SPC t ? lists only
- what the "t" group holds. Help writes into a "+Help" OUTPUT BUFFER,
- the same kind of pane "/" search results land in — so it opens below
- the pane you asked from, never in a column of its own — and ordinary
- text, so the names in it are live: middle-click "Tutor" and it opens.
-
- (No practice blocks: these run builtins, not text edits.)
+ SPC ? list every path
+ SPC k Kill SPC d Del
+ SPC f s Save SPC f f Find SPC f n New
+ SPC y Y p P R the system clipboard
+ SPC w h/j/k/l focus a neighbouring pane
+ SPC j j the pane before this one SPC j o/i back / forward
+ SPC s a Attach SPC s D Detach
+ SPC t * the toggles SPC l * the language
+ SPC h t this tutor
=================================================================
-= PART 4 — THE REST =
+= PART 6 — THE REST =
=================================================================
------------------------------------------------------------------
-= 4.1 PANES THAT ARE NOT TEXT: PDFs and images =
------------------------------------------------------------------
-
- Look at a .pdf and you get a PDF pane: the real document, rendered by
- MuPDF as one continuous strip of pages and placed like any other
- document (a leftmost column of its own the first time, split below a
- doc after that). Its tag is live, and reads
-
- pdf 3/128 width PdfFit filtered PdfTint PdfSections /path/to/it.pdf
-
- — the page you are on out of the count, then each of the three
- commands with its CURRENT setting written in front of it, then the
- path. Those are ordinary words: middle-click "PdfSections" and it
- runs.
-
- PdfFit (SPC t z) `width`, a reading column you scroll down, or
- `height`, the whole page at once panned sideways
- PdfTint (SPC t i) disabled -> filtered -> full -> disabled. `full`
- repaints the page in the theme's two colours;
- `filtered` starts from that and adds back three
- quarters of each channel's distance from the
- source's own luminance, so a COLOUR page keeps its
- hues and a grayscale scan comes out identical to
- `full`; `disabled` is the pixels as they are
- PdfSections (SPC t s) the document's OUTLINE, into a
- "+PdfSections" buffer below the PDF. An ordinary
- row is `file.pdf:PAGE:N` and the title, indented
- by depth; n/N walk them and Enter goes to that
- section. An entry that is a web LINK has no page
- to name, so its row is the bare URL and the title,
- and looking it opens a browser.
-
- The modal keys work on the PAGE rather than on a cursor: j/k scroll,
- Ctrl-d/u and Ctrl-f/b page, `Ngg` goes to page N, `ge` is the last
- page. `/` searches the document's real text through MuPDF and n/N walk
- the hits. Esc is the document's own CANCEL — it drops the selection and
- the search highlights and leaves you where you were reading — so the
- hop to the pane before this one is Shift-Esc here, the same chord that
- leaves a raw tty.
-
- The rest depends on the shell being able to place real PIXELS. Where
- it can, drag with the left button to select text (SPC y takes it), and
- h/l pan sideways with `0` and `$` for the edges — though there is
- nothing to pan while the page already fits, which in the default
- `width` fit is most of the time. Where it CANNOT, there is no text
- selection at all and the vertical keys step whole pages instead of
- scrolling.
-
- PDF support is a BUILD option: `-Dmupdf` is on for the native builds
- and off for the browser, and with it off a .pdf opens as the ordinary
- file it is on disk. `-Djpx` (also on) is what makes a SCANNED pdf
- render at all rather than as a stack of blank pages.
-
- An IMAGE — .png .jpg .jpeg .gif .bmp .ppm .pgm .tga — opens an image
- pane. Its tag reports `petscii:on/off`, `palette:commodore/terminal`,
- and `ascii:on/off` before the path, so every pane-local choice is
- visible even though only the builtins mutate it. Where the shell can place real pixels it
- does; where it cannot, the petscii matcher draws the picture out of
- block glyphs. The three toggles all act on THAT matcher, so with real
- pixels on screen only the first of them changes anything:
+ NOT TEXT
+ .pdf the real document through MuPDF. j/k scroll it, `/` searches
+ it, Esc cancels selection and highlights, Shift-Esc leaves.
+ PdfFit / PdfTint / PdfSections sit in its own tag.
+ images pixels where the shell has them, petscii glyphs where it
+ does not (SPC t p / l / a).
- Petscii (SPC t p) glyph art even when real pixels were available
- Palette (SPC t l) the C64's sixteen colours, or the terminal's own
- Ascii (SPC t a) whether the printable ASCII bitmaps join the
- matcher's glyph set. They start IN, so the first
- press takes them out and leaves the blocks
+ LANGUAGE — ZLS, compiled in, .zig only. Nothing runs in the background
+ and nothing is cached: gd gD gy gi gr, the ten SPC l words, ]d/[d and
+ ]D/[D, `=` for a format diff, and Tab after a dot in insert.
------------------------------------------------------------------
-= 4.2 THE LANGUAGE BACKEND =
------------------------------------------------------------------
-
- Pardes has ZLS compiled INTO it — not spawned, not spoken to over a
- socket, just called. So there is no server to start and nothing to
- wait for, and equally nothing kept warm: there is no cache at all, and
- every query re-parses from scratch — that is once per keypress, not
- once per file. It reads one language, `.zig`. On a file it does not
- read, the code queries below do nothing whatsoever: no error row, no
- message. (Four of them answer anyway, because they are not about this
- file's code — `SPC l i` and `SPC l w` describe the backend itself, and
- `SPC l S` and `SPC l D` walk the .zig files next door.)
-
- helix's five gotos keep helix's own letters, under `g`:
+ THE CONTROL FILESYSTEM — the extension mechanism, and there is no
+ plugin API, no interpreter and no rebuild. A program that opens files
+ IS an extension.
- gd definition gD declaration gy type definition
- gi implementation gr references
- Ctrl + left click the same as gd, with the mouse
+ pardes --fs acme's control files over FUSE
+ pardes --fs9 the same tree as 9P on a unix socket
- ONE answer jumps straight there. Several fill a "+Search" buffer, and
- from there it is the ordinary walk: n/N step the rows, Enter opens
- the one you stopped on.
+ A directory per pane holding `body`, `tag`, `ctl`, `addr`, `data`,
+ `event`, `pty/` and the rest, plus `index`, `cons` and `new/` at the
+ top. Every pane shell is told `$PARDES_FS` and `$PARDES_PANE`, so a
+ script in a pane addresses its own window with no arguments:
- The rest are BUILTINS — words you can middle-click as readily as
- press — under `SPC l`, each on helix's letter with the group prefix
- in front of it:
+ echo hello >> $PARDES_FS/$PARDES_PANE/body
+ cat $PARDES_FS/index
+ echo hi > $PARDES_FS/new/body
- SPC l k Hover what this thing is, into "+Hover"
- SPC l r Rename arms the tag; the new name goes after the
- `/`. One undo for all of it
- SPC l a CodeAction the titles of what could be done, into "+Lsp"
- SPC l h SelectRefs every reference, as rows
- SPC l s Symbols this file's symbols, parent-qualified
- SPC l S WsSymbols arms the tag; a substring match over the .zig
- files under the asking file's OWN directory
- SPC l d Diagnostics this file's; a clean file says so in one row
- SPC l D WsDiagnostics the same over that same directory
- SPC l i Lspinfo what the backend IS: its version, what it
- answers, what it refuses, and the last two
- dozen queries with how long each took
- SPC l w Lspwhy re-runs `gd` where the cursor is now, out
- loud: every step it took and where it stopped
+ A terminal pane also has `pty/`:
- ]d / [d step the diagnostics — asking for them if none are up
- ]D / [D the last / the first
- = format: a "+Lsp" buffer with one row per changed line,
- `- old + new` on each. It SHOWS you the
- formatting; it does not apply it
+ echo 'winsize 100 30' >> $PARDES_FS/3/pty/ctl
+ echo 'sig INT' >> $PARDES_FS/3/pty/ctl
+ echo 'make -j8' >> $PARDES_FS/3/pty/data
- Three limits worth knowing before you trust an answer. `gr`,
- `SelectRefs` and `Rename` are all the same resolution underneath, and
- it is THIS FILE ONLY — none of them claims a workspace. The two `S`/`D`
- walks start at the asking file's directory, not at the project root,
- and stop at 512 files. And a rename you did not want is one `u` away,
- because it lands as a single undo.
+ Over 9P the same tree answers plan9port, from anywhere:
- And in INSERT mode, Tab straight after a `.` asks what could go
- there. What comes back is not a popup and nothing is typed for you:
- it is a buffer of rows, one per candidate, each pointing at where
- that candidate is DECLARED. Picking one is looking at it. An empty
- answer indents instead, a moment late.
-
------------------------------------------------------------------
-= 4.3 CHROME, AND THE ONE FILE PARDES READS =
------------------------------------------------------------------
+ 9p -a $XDG_RUNTIME_DIR/pardes-9p-work.sock ls /
+ 9p -a $XDG_RUNTIME_DIR/pardes-9p-work.sock read /index
- Themes: 228 of them, described in Part 1. NextColor steps the ring,
- `Theme <name>` goes straight to one, ThemeSel (SPC t t) lists them
- all into a buffer you walk.
+ ...and pardes is a 9P CLIENT too, so one session can read another's:
- A native build can also wear one complete ZON file at runtime:
- `ThemeFile themes/mine.zon` resolves from the pardes config directory
- and, where document watching is available, reloads after every valid save.
- A broken save leaves the last good colors on screen. `DumpThemes` writes
- copyable references under themes/builtin; copy one out, rename it and edit
- that rather than guessing the fields.
+ 9p work.sock /1/body the `9p` word: opens it in a pane
- Fonts, on the SDL and macOS builds only — in a terminal the font
- belongs to the terminal and in a browser to the page. FontSel
- (SPC t f) lists every MONOSPACE face on the machine into a "+Fonts"
- buffer of `Font <name>` rows. n/N step those rows and select each one
- WHOLE, since a command line has no place inside it to pick out; Tab (or
- a middle click) runs the row you stopped on and puts that face on. So
- walking with n and pressing Tab is trying faces on, and stopping is
- choosing. `Font <name>` on its own takes the font file's stem.
- `TaglineSize 70` changes the tagline face and visible band to 70 percent
- of the body face, live; values 1 through 100 are accepted, `Config`
- reports the active value, and both native GUI renderers retain the same
- body cell grid while drawing that separate role.
+ TWO THINGS WORTH KNOWING. While a program holds a pane's `event` file
+ open, MIDDLE AND RIGHT CLICKS IN THAT PANE BELONG TO IT: pardes reports
+ them and performs nothing, so that pane's tag can carry the program's
+ own words (examples/acmefs/life.py puts Step/Run/Clear there). The
+ keyboard is never suppressed, and the clicks come back when it exits.
- Native panel transitions are the five SPC a choices listed in 3.13. They
- start off. Only one is selected; running it again turns it off. Slide and
- zoom animate geometry. Dissolve switches changed cells at stable thresholds.
- ASCII increments or decrements each changed printable byte toward its new
- value, using fast ease-out skips for long distances and exact steps nearby;
- unchanged glyphs and non-ASCII graphemes pass through. Vertical raises a pane being added
- and drops a deleted pane back down inside its own box; every survivor stays
- still. The native GUI scene switches Crt, Ripple
- and Glitch may be combined. `EffectCode PanelAscii` (or any other
- effect builtin as its argument) opens the exact backend sources that
- were embedded when this binary was built.
-
- Before its first frame a native pardes reads ONE file: `init` inside its
- `pardes` config directory — $XDG_CONFIG_HOME/pardes/init when that is
- set to an absolute path, else ~/.config/pardes/init, and on macOS
- ~/Library/Application Support/pardes/init. `SPC f c` opens a refreshable
- "+Config" buffer containing the resolved path and every live setting:
- theme, shell, requested/effective font, panel/scene effects, hover
- delay, and the ordinary display toggles. The path is printed whether
- or not anything is there, which is the case you ask in. (A right click
- on that row opens the file when there IS one. When there is not, the
- click has nothing to open and falls back to searching for the text —
- pardes will not create it for you.)
-
- Resting the pointer over look-able text for that reported delay paints
- a quiet preview of the exact operand a right click would expand. It is
- only a preview: it does not focus, select, move a cursor, or run Look.
- Set `look_preview_delay_frames` to null in src/config.zig to compile it
- out.
-
- The format is one BUILTIN COMMAND per line, spelled exactly the way
- you would execute it anywhere else:
-
- Theme gruvbox_dark_hard
- ThemeFile themes/mine.zon
- Shell zsh
- TaglineSize 70
- Tagbottom
-
- Blank, unknown or malformed lines are ignored in silence, and a bad
- line does not stop the ones after it. Two cautions. A word that is not
- a builtin is never handed to a shell — but `Exec` IS a builtin, so
- `Exec <anything>` in this file types that command into a shell before
- your first frame, and `Look` will run an `` @`...` `` word the same
- way. And every toggle here TOGGLES: `Wrap` in your config turns soft
- wrap OFF, because it starts on.
+ And writing an event record back — `origin type q0 q1` — makes pardes
+ perform the Look or Exec it names. That is arbitrary command execution
+ by design, the same door acme has always had, which is why the mount
+ sits under $XDG_RUNTIME_DIR at 0700 and why both flags are opt-in.
- It cannot remap a KEY, either: the keymap is src/config.zig, compiled
- in, and rebinding is an edit there and a rebuild — which is why a
- wrong binding is a compile error instead of a line that quietly did
- nothing.
+ examples/README.md is the client's guide; docs/acme-fs.md compares this
+ implementation with acme's file by file; docs/9p.typ is the 9P note.
- The browser build reads no such file, has no ptys, and has no language
- backend compiled in. It is not without a filesystem, though: LOOK
- there resolves against a read-only archive of working-tree .zig sources
- that was generated when the build was made. What you get is a dump,
- replayed, with those sources openable. (The core still ASKS for the
- rest. A host that answers gets terminals; that is the seam, not a
- special case.)
=================================================================
-= PART 5 — THE CONTROL FILESYSTEM (pardes --fs) =
+= SUMMARY =
=================================================================
- Started as `pardes --fs`, this session serves plan9 acme's control
- files over FUSE: a directory per pane, holding `body`, `tag`, `ctl`,
- `addr`, `data`, `event` and the rest, plus `index`, `cons` and `new/`
- at the top. Every pane shell gets `$PARDES_FS` (where it is mounted)
- and `$PARDES_PANE` (which pane it is), so a script run in a pane can
- talk to its own window with no arguments:
+ MOUSE L select/focus M execute R look(open)
+ 1-2 cut 1-3 paste both in one hold = snarf
+ 2-1 = execute the middle word with the left selection
+ keyboard: Enter = look, Tab = execute
- echo hello >> $PARDES_FS/$PARDES_PANE/body append to this pane
- cat $PARDES_FS/index one line per pane
- echo hi > $PARDES_FS/new/body open a pane holding "hi"
+ PANES Ctrl-w h/j/k/l focus a neighbour (SPC w h/j/k/l in a body)
+ Esc the pane you were in before this one
+ Shift-Esc leave, whatever Escape means in here
+ Ctrl-o / Ctrl-i jump history back / forward
+ Alt-n new terminal below Alt-c pane into a new column
- That IS the extension mechanism: no plugin API, no interpreter, no
- rebuild — a program that opens files. Two things about it are worth
- knowing before you use it.
+ TTY a terminal IS a pane
+ Ctrl-b or Shift-Esc toggles the shell, landing its cursor
+ where you navigated
+ Esc goes to the program — except at a shell PROMPT, where
+ it hops away like Shift-Esc
+ Ctrl-V default register, Ctrl-Shift-V system clipboard
- While a program holds a pane's `event` file open, MIDDLE AND RIGHT
- CLICKS IN THAT PANE BELONG TO IT: pardes reports them and performs
- nothing, so the words in that pane's tag can be the program's own
- commands (examples/acmefs/life.py puts Step/Run/Clear there). The
- keyboard is not suppressed, so the pane stays editable either way, and
- when the program exits the clicks come back.
+ DETACHED pardes --detach[=name] the core, no terminal
+ pardes --attach[=name] a frontend for it
+ Attach / Detach the same, as words (SPC s a / s D)
+ the pane shells belong to the SESSION and never stop
+ N frontends share ONE screen at the smallest common grid
+ --fs and --fs9 work in a daemon too
- And writing an event record back — `origin type q0 q1` — makes pardes
- perform the Look or Exec it names. That is arbitrary command execution
- by design, the same door acme has always had, which is why the mount
- lives under $XDG_RUNTIME_DIR at 0700 and why `--fs` is opt-in.
-
- examples/README.md is the client's guide; docs/acme-fs.md compares this
- implementation with acme's, file by file.
-
-=================================================================
-= SUMMARY =
-=================================================================
+ KEYS h j k l w b e 0 $ ^ gg ge f F t T v x d c y p
+ i a I A o O u undo U redo
+ motions SELECT, so `i` types at the selection's start and
+ `;` collapses first
+ a leading NUMBER is a count on motions, x, o/O, > <, p P,
+ Ctrl-a/x and ]space — not on the other edits
+ bare G does nothing; `ge` is the START of the last line
+ s / S regex cursors; m i/a textobjects; m s/r/d surround
+ ] [ paragraph, blank line, diagnostic; | pipe a selection
+ / is a case-insensitive SUBSTRING search, not a regex
+ SPC is the leader (SPC ? lists every path)
- MOUSE (acme): L select/focus+pin M execute R look(open)
- select-then-act: middle-drag, or v/x then Tab
- chords: 1-2 cut 1-3 paste (both in one hold = snarf)
- 2-1 = middle-exec with the left selection as argument
- every tag with text leads with Save (a terminal also
- has Filter); images and PDFs show "New Del"
- top bar = New Newcol Find Grep Help Tutor Dump ... Debug Kill
- (keyboard: k off the topmost tagline)
- WEB TOUCH: one-finger tap = LOOK; drag = natural scroll
- LOOK opens URLs or embedded working-tree .zig source (read-only)
- published TTY dump lists every source; tree-sitter colors it
- tag/separator start = left drag; touch HUD requires Debug
- TTY: a terminal IS a pane; Ctrl-b (or Shift-Esc) toggles the shell,
- landing its cursor where you navigated (prompt start if
- the input is empty, mid-text otherwise)
- Filter in its tag toggles a pane-local, theme-keyed palette
- --fs: acme's control files over FUSE: $PARDES_FS/<id>/{body,tag,
- ctl,addr,data,event,...} and $PARDES_FS/{index,cons,new}
- a script holding a pane's `event` open owns that pane's
- middle and right clicks; writing a record back runs it
- KEYS (helix): h j k l w b e 0 $ ^ gg ge f F t T v x X d c y p
- i a I A o O u undo U redo Enter=look Tab=execute
- w b e f F t T SELECT what they cross, so `i` after one
- types at the SELECTION's start; `;` collapses first
- a leading NUMBER is a count on the motions, x, o/O, > <,
- p P, Ctrl-a/x and ]space — not on the other edits
- bare G does NOTHING; `ge` is the START of the last line
- s / S = regex, one cursor per match, previewing as you
- type; C , ( ) Alt-s Alt-- Alt-_ _ work the LIST
- m i/a = textobjects (w W p, the bracket pairs and the
- three quotes), m s/r/d = surround, mm = match
- ] and [ = paragraph, blank line, diagnostic
- | = filter every selection through /bin/sh -c (a savable
- file pane only)
- : = the tag as a command line (arrows/words move in it,
- hjkl walk to the neighbouring TAGLINE, y/Enter act on
- the selection; the mode+path selects but never edits;
- k off the TOPMOST tagline = the top bar, j back down)
- zt zz zb zj zk Ctrl-d/u Ctrl-f/b Ctrl-o/i Ctrl-w hjkl
- Alt-n Alt-c
- Esc = the pane you were in before this one (body normal;
- in a PDF it cancels that document's own selection and
- search highlights instead, and Shift-Esc hops)
- n/N = select the next/prev look-able text, across panes
- (a ring); Enter opens what you landed on
- SPC = the leader: a key path runs a builtin (SPC ? lists
- them; SPC k Kill, SPC d Del, SPC f s Save, SPC f f Find,
- SPC f n New, SPC y/Y/p/P/R the system clipboard,
- SPC w hjkl focus, SPC j j the pane before this one,
- SPC t * the toggles, SPC l * the language backend)
- NOT TEXT: .pdf = the real document through MuPDF — j/k scrolls it,
- `/` searches it, Esc cancels selection+highlights and
- Shift-Esc leaves the pane, PdfFit/PdfTint/PdfSections
- sit in its own tag
- images = pixels where the shell has them, petscii glyphs
- where it does not (SPC t p/l/a)
- LANGUAGE: ZLS, compiled in, .zig only, nothing running in the
- background and nothing cached: gd gD gy gi gr, the
- ten SPC l words, ]d/[d and ]D/[D, `=` to see a
- format diff, and Tab after a dot in insert
+ SCRIPTING --fs acme's files over FUSE; --fs9 the same over 9P
+ $PARDES_FS/<id>/{body,tag,ctl,addr,data,event,pty/}
+ a script holding `event` owns that pane's middle and right
+ clicks; writing a record back runs it
- vs Helix: selection is LINE-first (x), plus v for characters; `/` is
- a case-insensitive SUBSTRING search, one hit per line, and
- not a regex one — the regex lives on s and S; the textobjects
- are w W p, the bracket pairs and the three quotes, with none
- of helix's tree-sitter ones.
- vs Vim: no verb+noun (dw) — because the MOTION already selected, so
- `wd` is what `dw` was; body-normal Esc hops focus; bare G is
- a no-op and `ge` goes to the start of the last line.
- vs both: a terminal is just a pane; the same keys edit text and
- navigate the shell screen, and the tty toggle reuses the
- shell's own prompt to position you precisely.
+ vs HELIX selection is LINE-first (x), v for characters; `/` is a
+ substring search, not a regex.
+ vs VIM no verb+noun — the motion already selected, so `wd` is
+ what `dw` was; Esc hops focus; bare G is a no-op.
+ vs BOTH a terminal is just a pane, and the core can outlive the
+ terminal that is showing it.
- To spawn THIS tutor again from anywhere: middle-click "Tutor" in the
- top bar (next to Help), or press SPC h t.
+ Spawn this tutor again: middle-click "Tutor" in the top bar, or SPC h t.
- Quit the tutor: this is a file pane — `:q` isn't wired; close the
- window (middle-click "Del" in its tag), "Kill" (top bar) to quit
- everything, or Ctrl-c the app.
+ Quit: this is a file pane — `:q` is not wired. Close it with Del in its
+ tag, "Kill" in the top bar to quit everything, or Ctrl-c the app.