1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
|
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 =
=================================================================
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 and edit. The box is BLANK.
^ INSERT keys type text at the cursor.
$ TTY keys go straight to the shell. (terminals only)
A bare `pardes` opens one shell already in TTY. Give it a file or a
directory and you start in NORMAL.
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. Raw input, prompt-aware Esc, and the mode tag.
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 5): the "# keys:" line lists keystrokes
(space-separated; esc/enter/bs are special, the rest type each char).
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) =
=================================================================
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.
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
Every tag with text leads with Save; a terminal also has Togglettymode
and Filter. Tty opens a terminal; New belongs to each column tag.
Images show "Tty Del Collapse"; PDFs also have PdfSections and PdfTint.
Every pane has Collapse: hide its body, then execute again to expand it.
The top bar is:
Newcol Joincol Find Grep Help Changelog Tutor Dump NextColor
Debug Exit
Reach it from the keyboard with `k` off the topmost tagline; `j` comes
back down.
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.
=================================================================
= PART 2 — PANES: MOVING BETWEEN THEM =
=================================================================
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.
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.
WHEN Esc MEANS SOMETHING ELSE
Three panes have their own claim on Escape, so there is a second
spelling that always leaves:
Shift-Esc leave this pane, whatever Escape means inside it
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.
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.
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 in a column tag: a new scratch pane
Newcol in the top bar: a pane in a new column
Tty new terminal in the calling pane's directory
Togglettymode in a terminal tag: switch editor/raw mode (Ctrl-B)
Joincol delete this column, move its panes to the one right
Del in a pane's own tag: close it. From the keyboard, between
two panes, it asks which one gets the space: k or j
DelAbove close it, giving the space to the pane above (Del k)
DelBelow close it, giving the space to the pane below (Del j)
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 TTY (a terminal is just a pane) =
=================================================================
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.
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.
ENTERING TTY
Ctrl-b toggle raw TTY/editor mode on a terminal pane
Shift-Esc also enters raw TTY from editor mode
Togglettymode in the pane tag switches modes in either direction
`pardes --tty-toggle=g` chooses Ctrl-g for toggling instead.
Entering TTY moves the shell's real cursor to the place you selected
on its prompt input line, using its OSC 133 prompt marks.
RAW INPUT
Ctrl-b switches to editor mode. Other keys go to the child,
including Ctrl-o, Ctrl-w, Alt shortcuts, and
modified Escape. The two paste chords are the exception: Ctrl-V
types the yank register at the program and Ctrl-Shift-V types the
desktop clipboard. Plain Esc at a detected shell prompt hops
to the previous pane. While a program owns the terminal, Esc goes
to that program too. Use the Togglettymode tag to leave raw input
in place. Desktop paste events still feed the child.
On Linux, Tty9p (SPC n 9 from editor mode) opens a terminal with
this session mounted through kernel v9fs. It asks sudo in that pane,
then starts your normal shell. $PARDES_MOUNT names its mounted tree.
`Filter` in a terminal's tag toggles a pane-local, theme-keyed palette.
=================================================================
= PART 4 — DETACHED SESSIONS (the core outlives the terminal) =
=================================================================
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.
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
And from inside a running editor, as ordinary acme words — type one in
a tag and execute it, or press its chord:
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)
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.
`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.
`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.
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.
WHAT A DAEMON CAN ALSO DO
A detached session serves acme's control filesystem like any other:
pardes --detach=work 9P on the session's default unix socket
Every native session is scriptable over 9P — see part 6.
The socket lives in $XDG_RUNTIME_DIR (else ~/.local/state/pardes),
created 0700, never /tmp: it carries keystrokes into a live editor.
=================================================================
= 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.
-----------------------------------------------------------------
= 5.1 MOTION AND COUNTS =
-----------------------------------------------------------------
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
Bare G does NOTHING. `ge` is the start of the last line.
# keys: l l l
# before
abcdef
# after
abcdef
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: 3 l i Z esc
# before
abcdef
# after
abcZdef
-----------------------------------------------------------------
= 5.2 ENTERING INSERT =
-----------------------------------------------------------------
`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: i X esc
# before
abc
# after
Xabc
# keys: o line2 esc
# before
line1
# after
line1
line2
-----------------------------------------------------------------
= 5.3 MOTIONS SELECT =
-----------------------------------------------------------------
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.
# keys: w ; i Z esc
# before
one two
# after
one Ztwo
-----------------------------------------------------------------
= 5.4 SELECT AND EDIT =
-----------------------------------------------------------------
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
Selection is LINE-first here — `x` — with `v` for characters. That is
the main divergence from helix.
# keys: x c typed esc
# before
replace me
# after
typed
-----------------------------------------------------------------
= 5.5 THE REST, IN ONE PLACE =
-----------------------------------------------------------------
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).
-----------------------------------------------------------------
= 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; 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.
SPC ? list every path
SPC d Del Exit (quit) remains available in the topbar.
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 6 — THE REST =
=================================================================
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).
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.
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.
pardes the 9P socket opens by default
A directory per pane holding `name`, `body`, `tag`, `addr`, `dot`,
`data`, `sel`, `dirty`, `event`, `pty/` and the rest, plus `index`,
`status`, `look`, `exec` and `log` at the root. Every pane shell
receives `$PARDES_9P` (the socket) and `$PARDES_PANE` (its serial):
/pane/<serial>/body
/index
/pane/new open it to make a pane; rmdir closes one
/look /exec `FILE:12` and `Save`, as the mouse does
A terminal pane also has `pty/`:
/pane/3/pty/ctl winsize, sig
/pane/3/pty/data terminal input/output
Over 9P the same tree answers plan9port, from anywhere:
9p -a $XDG_RUNTIME_DIR/pardes-9p-work.sock ls /
9p -a $XDG_RUNTIME_DIR/pardes-9p-work.sock read index
...and pardes is a 9P CLIENT too, so one session can read another's:
pardes --mount=peer=work
/n/peer/pane/1/body Look opens the other session's body
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. The keyboard is never suppressed, and the clicks come back
when it exits.
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 socket sits in the user's private runtime directory.
docs/fs.md describes the filesystem and mount paths.
=================================================================
= SUMMARY =
=================================================================
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
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
TTY a terminal IS a pane
Ctrl-b toggles raw input; Shift-Esc enters from editor mode
Togglettymode in the tag switches modes in either direction
Esc goes to the program — except at a shell PROMPT, where
it hops to the previous pane
Ctrl-b switches to editor mode
Ctrl-V types the register, Ctrl-Shift-V the clipboard
All other keys belong to the child
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
the default 9P socket works in a daemon too
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)
SCRIPTING 9P is served by default on $PARDES_9P
/pane/<id>/{name,body,tag,ctl,addr,data,sel,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), 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.
Spawn this tutor again: middle-click "Tutor" in the top bar, or SPC h t.
Quit: this is a file pane — `:q` is not wired. Close it with Del in its
tag, "Exit" in the top bar to quit everything, or Ctrl-c the app.
"Kill" does not quit: it stops the commands pardes started, as acme's does.
|