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): nm NORMAL block cursor, keys move/edit. DEFAULT on startup. in INSERT keys type text at the cursor. sy 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 drops into it by default. 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. 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). SELECT-THEN-ACT: there is no held-button chord. Instead: - 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. THE TAG: each pane has a one-line tag: its MODE (nm/in/sy) + directory or file path + builtins. File panes show "Save Del" by default; Save writes the current file to disk, Del closes the window. 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 Colors NextColor Middle-click "Newcol" for a new column, "Tutor" to spawn this tutor, "Kill" to quit; Debug/Colors/NextColor toggle the stats overlay, the syntax/ansi recolor, and the theme. Right-click a directory in any body to open a terminal there. 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 - 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 (Mouse actions are hard to unit-test from text; they're covered by the e2e suite: middle-click execute, right-click dir/file open, tag builtins, drag-rearrange. See tests.zig steps 6-8.) ================================================================= = 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 (nm) 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 (in) same clean page; keys type an insertion overlay (the command you're composing). Prompts still hidden. TTY (sy) the REAL shell — prompts + typed input shown, and keys go straight to the pty as terminal input. ESC: insert -> normal. (Esc never reaches tty.) Ctrl-b: toggles TTY on a terminal by default — the ONLY way 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`. - ESC never reaches tty; it only does insert -> normal. Dropping a terminal into the live shell is the tty toggle (Ctrl-b by default; see Part 2). - Enter / Tab in normal mirror the mouse: Enter = look (open the path under the cursor), Tab = execute. `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 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.) ================================================================= = SUMMARY = ================================================================= MOUSE (acme): L select/focus+pin M execute R look(open) select-then-act: middle-drag, or v/x then Tab file tag = mode + path + "Save Del"; other tags show Del top bar = Kill Newcol Tutor Debug Colors NextColor TTY: a terminal IS a pane; Ctrl-b toggles the live shell by default, 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 zt zz zb Ctrl-d/u Ctrl-f Ctrl-w hjkl Alt-n/c 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). 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.