PARDES TUTOR tmux + vi + acme, from scratch. The model is acme's: EVERYTHING is text, editable and executable the same way. Modal editing (helix-style) lives on top of that. Press j until you reach the introduction. ================================================================= = 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. Three modes (the tag shows which): NOR NORMAL block cursor, keys move/edit. DEFAULT on startup. INS INSERT keys type text at the cursor. TTY TTY keys go straight to the shell. (terminals only) This tutor is in THREE 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). PRACTICE BLOCKS (part 3): 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. These blocks are also run as unit tests (generated from this file by tutor_gen). Hold j to reach part 1. ================================================================= = PART 1 — THE MOUSE (acme chording; the most different part) = ================================================================= 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.) ┌─────────┬─────────┬─────────┐ │ L │ M │ R │ │ (1) │ (2) │ (3) │ ├─────────┴─────────┴─────────┤ │ │ │ ( o ) │ the wheel scrolls the pane │ │ └─────────────────────────────┘ L select a plain click also FOCUSES the pane and PINS the modal cursor where you click, so you can edit there next. A click never changes a pane's MODE (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). 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 Git-tracked and embedded when the web build was made. The published launcher is a real Pardes terminal dump of `git ls-files '*.zig'`: every listed path opens, and the opened source uses tree-sitter syntax 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 LOOK flash appear only while the Debug builtin is on. 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. 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 other panes' are searched (active pane first) — 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. The selection a chord leaves behind is dismissed by the next left click (it doesn't stretch to the click). THE TAG: each pane has a one-line tag: its MODE (NOR/INS/TTY) + directory or file path + builtins. File panes show "Save Del" by default; Save writes the current file to disk, Del closes the window. Clicking a tag edits it in insert mode: type straight in, Enter looks / Tab executes the word at the cursor, Esc hands focus back to the body. `:` from the body focuses that same tag in NORMAL mode, parked at its start — vim's command line with acme's words in it: `:w` 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). Terminal and image panes show "Del". "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: Kill Newcol Tutor Debug NextColor Dump Middle-click "Newcol" for a new column, "Tutor" to spawn this tutor, "Kill" to quit; Debug toggles the stats overlay and NextColor cycles the theme. The bar holds only what you reach for often — the rest of the builtins are words you execute and keys you press. Every one of them has a KEY PATH under SPC (part 3.7): "Colors" (the syntax/ansi recolor) is SPC t c, "Crt" is SPC t r, 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 hit into a "+Search" pane. That is an OUTPUT BUFFER: a file pane with no file behind it, so it has no Save, but everything else about it is an ordinary buffer you can read, edit, select and look in. `n`/`N` step the rows and look each one, so the view follows along. Right-clicking a word that names no file searches for it the same way — acme's button 3 — everywhere except a shell in tty mode, where the click belongs to the program on the other end. On a shell with no search armed, n/N instead step the lookable tokens in its output. A hit in a file reads `path:LINE:COL`, the ordinary look target. A hit in a shell or an output buffer has no file to name, so it reads `@pN:LINE:COL` — pane N, line LINE, column COL. Looking either one goes there; the column is optional (`main.zig:100`, `@p3:12`) and you can type one yourself anywhere text lives. 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 step them and each found file opens; the match is on the name, plain and case-insensitive, ".git" is skipped. 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 accent box (top-left of a pane; indigo-purple, brighter when the pane is focused) 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 file/image/tutor you open takes a new leftmost column of its own (nothing is displaced, the other columns just narrow); every later one 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 (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`.) ================================================================= = PART 2 — THE TTY (a terminal is just a pane) = ================================================================= 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. On a terminal pane: NORMAL (NOR) prompt rows are HIDDEN — a clean acme-style page. You navigate it with the same h/j/k/l/w/b/e as a file. INSERT (INS) same clean page; keys type an insertion overlay (the command you're composing). Prompts still hidden. TTY (TTY) the REAL shell — prompts + typed input shown, and keys go straight to the pty as terminal input. ESC: insert -> normal. (A plain Esc never reaches tty.) Ctrl-b: toggles TTY on a terminal by default; SHIFT-ESC is the same toggle, where the host reports modifiers on Escape. Those are the ONLY ways in or out. Use `pardes --tty-toggle=g` (or another letter) to make Ctrl-g the toggle instead. 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 — - empty input -> shell cursor at the prompt START - typed text -> shell cursor at/after the char you were on 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. 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. 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. (The cursor positioning is enterTty's promptClickMove; it needs a live shell at a prompt. Mouse/tty behavior is exercised by the e2e suite.) ================================================================= = PART 3 — THE KEYS (helix-style modal, Pardes differences) = ================================================================= Same core as Helix and Vim: a block cursor you move with h/j/k/l, motions w/b/e, and you enter insert with i/a/o. The differences: - Selection is LINE-first: `x` grows a line selection downward. There's also `v` for a CHARACTER range. No multi-cursor. d/c/y act on whichever selection is active (else the current line). - NO verb+noun (Vim's dw, cw). Motions only MOVE. To delete a word, select it (`v` then motions, or `x` for whole lines) then `d`. - A plain ESC never reaches tty; it only does insert -> normal. 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. - 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). PRACTICE: run the keys on the "# before" lines; you should get the "# after" lines. (These blocks are unit tests too.) ----------------------------------------------------------------- = 3.1 MOVING THE CURSOR (h j k l) = ----------------------------------------------------------------- k * h = left, l = right h l * j = down, k = up (also: arrow keys) j The cursor sits ON a character (block). Motions only move. # keys: l l l # before abcdef # after abcdef ----------------------------------------------------------------- = 3.2 ENTERING INSERT: i a A I o O = ----------------------------------------------------------------- `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.) # keys: i X esc # before bcdef # after Xbcdef Cursor on 'b' (col 0). `i` inserts before 'b'. # keys: a Z esc # before abc # after aZbc Cursor on 'a' (col 0). `a` inserts after 'a'. # keys: A Z esc # before abc # after abcZ `A` jumps to end then inserts — appends 'Z'. # keys: I Z esc # before abc # after Zabc `I` goes to the first non-blank ('a'), inserts before it. # keys: o line2 esc # before line1 # after line1 line2 `o` makes a blank line below, enters insert, "line2" typed, Esc. # keys: O top esc # before bot # after top bot ----------------------------------------------------------------- = 3.3 WORD MOTIONS: w b e (W B E long) = ----------------------------------------------------------------- `w` next word start, `b` prev word start, `e` next word END. W/B/E treat punctuation as part of the word. Same as Vim & Helix. # keys: w i Z esc # before foo bar # after foo Zbar `w` from 'f'(col0) lands on 'b'(col4). Insert before 'b'. # keys: e i Z esc # before foo bar # after foZo bar `e` from 'f' lands on 'o'(col2, end of "foo"). Insert before it. # keys: b i Z esc # at: 0,4 # before foo bar # after Zfoo bar Cursor on 'b'(col4, "bar"). `b` -> start of previous word = 'f'(col0). ----------------------------------------------------------------- = 3.4 LINE BOUNDS: 0 $ ^ g g G = ----------------------------------------------------------------- `0` start of line, `$` end, `^` first non-blank. `gg` first line, `G` last line. Same as Vim/Helix. # 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.) # keys: 0 i Z esc # before abcde # after Zabcde # keys: ^ i Z esc # before abcde # after Zabcde ----------------------------------------------------------------- = 3.5 LINE SELECTION + EDIT: x d c y p = ----------------------------------------------------------------- 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 `d` delete the selected lines (yanked) `c` clear the line + insert (change) `y` yank the selection (or current line) `p` paste the yank as a new line below # keys: x d # at: 1,0 # before keep gone # after keep 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. # keys: x c typed esc # before old # 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'. ----------------------------------------------------------------- = 3.6 VIEWPORT + PANES = ----------------------------------------------------------------- zt / zz / zb scroll so the cursor is at top/center/bottom 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-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) Alt-n new terminal below the active one Alt-c move the active terminal into a fresh column (No practice blocks: these are viewport/layout, not text edits.) ----------------------------------------------------------------- = 3.7 SPC — THE LEADER = ----------------------------------------------------------------- Every builtin has a NAME you can execute anywhere text lives, and a KEY PATH you can press. SPC in normal mode starts the path; the keys you have typed so far show at the right edge of the pane's tag until the sequence fires. Esc abandons it — so does any key that leads nowhere, rather than leaving the next keystroke armed. SPC ? Help: every builtin and the keys that run it SPC k Kill (quit) SPC d Del (close this pane) SPC f s / f f Save / Find SPC h t Tutor (this file) SPC c n / c d Newcol / Delcol SPC t d/c/n/r Debug / Colors / NextColor / Crt toggles SPC t p/l/a Petscii / Palette / Ascii: an image pane's renderer — glyph art instead of pixels, the C64 palette or the terminal's own 16, and whether letters join the matcher's glyph set 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 w t Toggleterm: hop between the last document you looked at and the last terminal, and back `?` works at ANY depth: SPC ? lists everything, SPC h ? lists only what the "h" group holds. Help writes into a "+Help" OUTPUT BUFFER, the same kind of pane "/" search results land in — ordinary text, so the names in it are live: middle-click "Tutor" there and it opens. (No practice blocks: these run builtins, not text edits.) ================================================================= = SUMMARY = ================================================================= 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 file tag = mode + path + "Save Del"; other tags show Del top bar = Kill Newcol Tutor Debug NextColor Dump WEB TOUCH: one-finger tap = LOOK; drag = natural scroll LOOK opens URLs or embedded tracked .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) KEYS (helix): h j k l w b e 0 $ ^ gg G v x d c y p i a I A o O u undo U redo Enter=look Tab=execute : = the tag as a command line (motions, Enter, back) zt zz zb Ctrl-d/u Ctrl-f Ctrl-w hjkl Alt-n/c 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 w hjkl focus, SPC w t file <-> terminal) vs Helix: no multi-cursor; selection is LINE-first (x), plus v chars. vs Vim: no verb+noun (dw); motions only move; Esc never reaches tty. 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. To spawn THIS tutor again from anywhere: middle-click "Tutor" in the top bar (next to Kill / Newcol), or press 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.