summaryrefslogtreecommitdiff
path: root/src/tutor.txt
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-08-12 13:32:43 -0300
committerGabriel Schneider <[email protected]>2026-08-12 16:07:33 -0300
commitbc89f57cb576e23a58572ec35f96db068367f1b4 (patch)
tree06f1ea2b7e95f229c10b316214ae904b9d43e343 /src/tutor.txt
parentb424164922842796619cb6894ec46d729a8a6826 (diff)
downloadpardes-bc89f57cb576e23a58572ec35f96db068367f1b4.tar.gz
pardes-bc89f57cb576e23a58572ec35f96db068367f1b4.zip
docs: the tutor taught three keystrokes wrong, and the rest had drifted
The documentation had gone stale in the ordinary way -- claims that were true when they were written and that nothing since had been obliged to re-read. Some of them were load-bearing. THE TUTOR. It still said there is no multi-cursor, that NextColor cycles three themes, and that its practice blocks "are also run as unit tests (generated from this file by tutor_gen)" -- a tool that appears nowhere in the tree, and nothing anywhere parses a `# keys:` block. Left alone, that claim is what makes the next wrong block survive. Three of those blocks WERE wrong, and all three for one reason: since the helix motion model landed, w/e/f/t SELECT the range they cross, so `i` after one inserts at the SELECTION'S START. `w i Z esc` on "foo bar" gives "Zfoo bar", not the "foo Zbar" the file promised. They were written against a vim reading of the same keys. Every block in the file has now been run through `zig build hxdiff` against the real core and matches byte for byte, and the trap itself is written down in 3.3 rather than left to be rediscovered. The tutor gains a PART 4 for everything added since it was written -- PDF panes, the in-process ZLS backend, themes and fonts, the startup file -- and PART 3 gains counts (and which keys ignore one), f/F/t/T, the whole g table (bare `G` is a no-op; `ge` is the START of the last line), multiple cursors and the s/S regex pair, `m`, `]`/`[`, `|`, insert mode, and all fifty leader paths. THE REST. design.typ's line table claimed 7,626 lines against a real 38,048, and its rows did not sum to its own total; its Event/Effect boundary contract -- the part a shell author writes against -- named four variants that do not exist and omitted fourteen that do. lsp.md's probe count. config.md's theme-name rules, which as written could not reach a zed theme at all. helix-keys.md's Skipped section, holding five families that have since landed. macos.md's menu bar, undocumented, along with sixteen other claims. web.md on what the browser build can actually do. SOURCE COMMENTS that had rotted alongside them: `tag_normal` is a space, not the `•` its own comment describes; Wrap is ON by default, not off; a FontSel row is SELECTED by n and RUN by Tab, not run by n; the SPC paths in lsp.zig lost their `l` group prefix when the language group moved; and the differential suites are 481 and 561 cases, not 360 and 440. TWO THINGS FOUND BY DOCUMENTING THEM, both left standing and written down rather than papered over. Typing `[^\n]` at an s/S prompt panics: the live preview compiles every prefix, and `[^\` indexes an empty slice in mvzr's parseCharSet. Both the tutor and a waiver recommended that pattern as the workaround for `.` matching a newline; they now say what it costs and what would make it sayable. And `Exec` is a builtin, so an `Exec` line in the startup config types that command into a shell before the first frame -- the tutor said nothing in that file is ever sent to one. Nine adversarial reviews over two rounds, each with the hxdiff harness to execute what it doubted. The second round exists because the first round's fixes needed checking too, and it caught three regressions of my own -- one of them a probe count I had "corrected" away from the truth. Verified: unit-test, snap 87/87, hxdiff 481/0, hxparity 561/0, mupdf-check. docs/design.pdf regenerated. The tutor's first seventeen lines are byte- identical, which is what tutor.golden pins.
Diffstat (limited to 'src/tutor.txt')
-rw-r--r--src/tutor.txt988
1 files changed, 778 insertions, 210 deletions
diff --git a/src/tutor.txt b/src/tutor.txt
index fe80c9e3..9c73e5c9 100644
--- a/src/tutor.txt
+++ b/src/tutor.txt
@@ -18,23 +18,35 @@
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. DEFAULT on startup.
+ 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)
- This tutor is in THREE parts, ordered by what's most different from
+ 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. These blocks are also run as unit
- tests (generated from this file by tutor_gen).
+ (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.
@@ -56,9 +68,11 @@
│ │
└─────────────────────────────┘
- 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).
+ 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.
@@ -66,8 +80,9 @@
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 every other open pane's, most recently used first — a
- name none of them holds is what becomes a search.
+ 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.
@@ -80,8 +95,9 @@
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.
+ 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);
@@ -98,13 +114,15 @@
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.
+ 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.
+ 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).
@@ -114,13 +132,18 @@
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
- the word at the cursor, Esc hands focus back to the body. `:` from the
- body focuses that same tag in NORMAL mode, parked at the first EDITABLE
- column — vim's command line with acme's words in it: `:w<Tab>` is w
+ 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). Terminal and image panes
- show "New Del".
+ 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
@@ -129,36 +152,50 @@
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 MODE + path part 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 W/E
- selects the path, `y` yanks it, Enter looks it. Typing or backspacing
+ 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
- exactly as a middle-click on it would, j drops back onto the tagline
+ 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 overlay
- and NextColor cycles the theme: "helix" (the default — a near-black
- page and chrome that barely lifts off it, copied from helix's own), then
- "dark", then the acme-light yellow. 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.
+ 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 hit into a "+Search" pane.
+ 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.
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
@@ -173,12 +210,16 @@
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. `N` is `n` backwards exactly: ten
- forward and ten back is where you began.
+ 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 the click belongs to the program on the other end.
- A hit in a file reads `path:LINE:COL-ENDCOL`, the ordinary look target
+ 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
@@ -193,7 +234,10 @@
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, ".git" is skipped.
+ 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
@@ -208,9 +252,10 @@
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
+ - 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
@@ -230,12 +275,16 @@
prompt model rather than layering an editor cursor on top.
On a terminal pane:
- NORMAL (•) 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 (^) same clean page; keys type an insertion overlay (the
- command you're composing). Prompts still hidden.
- TTY ($) the REAL shell — prompts + typed input shown, and keys
- go straight to the pty as terminal input.
+ 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
@@ -245,12 +294,11 @@
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` (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
+ 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.
@@ -271,30 +319,47 @@
= 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:
+ 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.
- 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).
+ - 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. (These blocks are unit tests too.)
+ "# after" lines.
-----------------------------------------------------------------
-= 3.1 MOVING THE CURSOR (h j k l) =
+= 3.1 MOVING THE CURSOR (h j k l), AND COUNTS =
-----------------------------------------------------------------
k * h = left, l = right
@@ -303,11 +368,28 @@
The cursor sits ON a character (block). Motions only move.
- # keys: l l l
- # before
- abcdef
- # after
- abcdef
+# 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
-----------------------------------------------------------------
@@ -319,53 +401,53 @@
`o` open line BELOW + insert. `O` open line ABOVE + insert.
(All match Vim and Helix.)
- # keys: i X esc
- # before
- bcdef
- # after
- Xbcdef
+# 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
+# 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
+# keys: A Z esc
+# before
+abc
+# after
+abcZ
`A` jumps to end then inserts — appends 'Z'.
- # keys: I Z esc
- # before
- abc
- # after
- Zabc
+# 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
+# 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
+# keys: O top esc
+# before
+bot
+# after
+top
+bot
-----------------------------------------------------------------
@@ -373,65 +455,130 @@
-----------------------------------------------------------------
`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.
+ 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 i Z esc
- # before
- foo bar
- # after
- foo Zbar
+# keys: w d
+# before
+foo bar
+# after
+bar
- `w` from 'f'(col0) lands on 'b'(col4). Insert before 'b'.
+ `w` from 'f'(col0) selects "foo " up to 'b'(col4); `d` deletes it.
- # keys: e i Z esc
- # before
- foo bar
- # after
- foZo bar
+# keys: e d
+# before
+foo bar
+# after
+ bar
- `e` from 'f' lands on 'o'(col2, end of "foo"). Insert before it.
+ `e` selects to the END of "foo" and no further, so the space stays.
- # keys: b i Z esc
- # at: 0,4
- # before
- foo bar
- # after
- Zfoo bar
+# keys: b d
+# at: 0,4
+# before
+foo bar
+# after
+bar
- Cursor on 'b'(col4, "bar"). `b` -> start of previous word = 'f'(col0).
+ 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: 0 $ ^ g g G =
+= 3.4 LINE BOUNDS AND GOTO: 0 $ ^ and the g prefix =
-----------------------------------------------------------------
- `0` start of line, `$` end, `^` first non-blank.
- `gg` first line, `G` last line. Same as Vim/Helix.
+ `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
+# 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: 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
- # keys: ^ i Z esc
- # before
- abcde
- # after
- Zabcde
+ `fd` selects "abcd"; `d` deletes it.
+
+# keys: t d d
+# before
+abcdef
+# after
+def
+
+ `td` stops one short, so only "abc" goes.
-----------------------------------------------------------------
-= 3.5 LINE SELECTION + EDIT: x d c y p =
+= 3.6 SELECTION + EDIT: x v d c y p, and the rest =
-----------------------------------------------------------------
The Pardes difference is LINE-first selection: `x` grows a line
@@ -439,70 +586,243 @@
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 (or current line)
- `p` paste the yank as a new line below
+ `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
+# 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
+# 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
+# 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
+# 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
+# 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.6 VIEWPORT + PANES =
+= 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)
@@ -510,50 +830,82 @@
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 terminal into a fresh column
+ 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.7 SPC — THE LEADER =
+= 3.13 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.
+ 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/f f/f n Save / Find / New SPC h t Tutor (this file)
+
+ 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 main cursor's alone)
+ 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 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 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 are helix's own clipboard letters, and the only words that
- reach the desktop's clipboard at all: ordinary y d c p P R and the
- 1-2 / 1-3 chords all 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.
+ 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.
- `?` works at ANY depth: SPC ? lists everything, SPC h ? lists only
- what the "h" group holds. Help writes into a "+Help" OUTPUT BUFFER,
+ 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.
@@ -562,6 +914,192 @@
=================================================================
+= 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 =
=================================================================
@@ -569,7 +1107,8 @@
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"; other tags show "New Del"
+ 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
@@ -579,23 +1118,52 @@
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
+ 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 Ctrl-d/u Ctrl-f Ctrl-w hjkl Alt-n/c
- Esc = last document <-> last terminal (body normal)
+ 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 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: no multi-cursor; selection is LINE-first (x), plus v chars.
- vs Vim: no verb+noun (dw); motions only move; body-normal Esc hops focus.
+ 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.