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
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
|
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 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.
^ 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 — there is nothing to
edit yet. 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.
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. 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.
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, 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.
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 click flash are the SDL
build's debug overlay, drawn only while the Debug builtin
is on. The browser draws no such thing.
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 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).
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.
File panes show "Save New 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
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). Everything else — a
terminal, an image, a PDF, an output buffer like "+Search" — shows the
plain "New Del", because there is no file behind it to Save. 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 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 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 it has
no Save, but everything else about it is an ordinary buffer you can read,
edit, select and look in. 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. 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.
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 (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 ( ) 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.
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: 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:
- 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).
PRACTICE: run the keys on the "# before" lines; you should get the
"# after" lines.
-----------------------------------------------------------------
= 3.1 MOVING THE CURSOR (h j k l), AND COUNTS =
-----------------------------------------------------------------
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
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.
# keys: 3 l i Z esc
# before
abcdef
# after
abcZdef
-----------------------------------------------------------------
= 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 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
`e` selects to the END of "foo" and no further, so the space stays.
# keys: b d
# at: 0,4
# before
foo bar
# after
bar
Cursor on 'b'(col4, "bar"). `b` selects back to 'f'(col0).
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`.
# keys: w ; i Z esc
# before
foo bar
# after
fooZ bar
-----------------------------------------------------------------
= 3.4 LINE BOUNDS AND GOTO: 0 $ ^ and the g prefix =
-----------------------------------------------------------------
`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.)
# keys: 0 i Z esc
# before
abcde
# after
Zabcde
# keys: ^ i Z esc
# before
abcde
# 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 line down gk 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.
Five more gotos live under the same prefix — gd gD gy gi gr — and
they belong to the language backend, in part 4.2.
-----------------------------------------------------------------
= 3.5 FINDING A CHARACTER: f F t T =
-----------------------------------------------------------------
`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.
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
# before
abcdef
# after
def
`td` stops one short, so only "abc" goes.
-----------------------------------------------------------------
= 3.6 SELECTION + EDIT: x v d c y p, and the rest =
-----------------------------------------------------------------
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
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'.
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 real FILE pane, and only that: the gate is whether the pane has a file
to Save, so `|` is inert in a terminal and in every output buffer, and
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 =
-----------------------------------------------------------------
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)
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.)
-----------------------------------------------------------------
= 3.13 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 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.
The groups are shared first letters and nothing cleverer: f files,
h docs, c columns, t toggles, 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 Crt SPC t f FontSel (gui and macOS only)
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
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.)
=================================================================
= PART 4 — 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.
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, tagged `img <path>`. 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:
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
-----------------------------------------------------------------
= 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`:
gd definition gD declaration gy type definition
gi implementation gr references
Ctrl + left click the same as gd, with the mouse
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.
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:
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
]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
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.
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 =
-----------------------------------------------------------------
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.
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.
Before its first frame a native pardes reads ONE file: a file called
`pardes` in your config directory — $XDG_CONFIG_HOME/pardes when that
is set to an absolute path, else ~/.config/pardes, and on macOS
~/Library/Application Support/pardes. `SPC f c` prints the resolved
path into a "+Config" buffer 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.)
The format is one BUILTIN COMMAND per line, spelled exactly the way
you would execute it anywhere else:
Theme gruvbox_dark_hard
Shell zsh
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.
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.
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 the tracked .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.)
=================================================================
= 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 = path + "Save New Del"; everything else,
output buffers included, shows "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 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 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)
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, 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
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.
To spawn THIS tutor again from anywhere: middle-click "Tutor" in the
top bar (next to Help), 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.
|