summaryrefslogtreecommitdiff
path: root/docs/typ/guide.typ
diff options
context:
space:
mode:
Diffstat (limited to 'docs/typ/guide.typ')
-rw-r--r--docs/typ/guide.typ303
1 files changed, 303 insertions, 0 deletions
diff --git a/docs/typ/guide.typ b/docs/typ/guide.typ
new file mode 100644
index 00000000..080ed5ea
--- /dev/null
+++ b/docs/typ/guide.typ
@@ -0,0 +1,303 @@
+// The guide: pardes day to day, read once in about ten minutes. The
+// cheatsheet is the index of keys and words; the reference has every
+// 9P file; scripting has the recipes.
+#import "style.typ": key, keys, btn, chord, word, tag, addr, file, cmd, doc, pairs
+
+pardes is a screen of columns. Each column holds panes, and each pane is a
+tag (a line of words) over a body: a file, a terminal, a PDF or an image.
+Above the columns runs the workspace tag, and each column has a tag of its
+own. Any text anywhere can be clicked: #btn("B2") runs it, #btn("B3") looks
+at it. The keys are helix's, in modes.
+
+= Modes <modes>
+
+Each pane has its own mode and keeps it while you are elsewhere: leave a
+terminal at its `$` and it is still `$` when you come back. The box at the
+left of a pane's tag shows the mode.
+
+#pairs(
+ [normal (box blank)], [keys move and select; an edit acts on the selection. File and PDF panes start here, and so does a terminal from #key("Alt-n").],
+ [insert (`^`)], [keys type. #keys("i", "a", "o") and the rest enter it.],
+ [raw (`$`), terminals only], [keys go to the program. A terminal from #word("Tty"), the shell a bare `pardes` starts with, and a command pane start here.],
+)
+
+#key("Ctrl-b") switches a terminal between raw and normal; in normal mode
+the shell's prompts are hidden and its text is a page to move over and
+copy from. #word("Mode") in the tag steps raw, normal, insert. Esc and
+Shift-Esc depend on the mode:
+
+#pairs(
+ [normal], [#key("Esc"): back to the previous pane (#word("Last")). #key("Shift-Esc"): the same, except in a terminal, where it switches to raw.],
+ [insert], [#key("Esc"): back to normal. #key("Shift-Esc"): the same, except in a terminal, where it switches to raw.],
+ [raw `$`], [#key("Esc"): to the program, except at an idle, empty shell prompt, where it goes back to the previous pane. #key("Shift-Esc"): always back to the previous pane. Either way the terminal stays `$`.],
+ [a PDF], [#key("Esc"): clears the selection and the search highlights. #key("Shift-Esc"): back to the previous pane.],
+)
+
+"The previous pane" is the last other pane on the jump list; with none, the
+next pane down its column (wrapping), else any other pane. In raw mode
+every key but #key("Ctrl-b"), Esc and the paste chords goes to the
+program, so #key("Ctrl-w") and #key("Alt-n") need you out of raw mode
+first (and #key("Ctrl-w") out of insert mode, where it deletes a word).
+
+= The mouse <mouse>
+
+#pairs(
+ btn("B1"), [select; a plain click puts the cursor there and gives the pane the keyboard. In a tag it starts typing at the click, in insert mode. A double click selects the word, the line (at a line's start or end), or up to the matching bracket or quote.],
+ btn("B2"), [execute: a builtin word runs, anything else is a shell line.],
+ btn("B3"), [look: open the file, address, directory or URL, or else find the word's next place.],
+)
+
+A #btn("B2") or #btn("B3") click with no drag takes the word under it,
+where a word is the run of letters, digits, non-ASCII and `. - + / : @ _ ~`
+around the click; a trailing `:` is dropped. So #btn("B3") anywhere on
+`src/bar.c:12:5:` in a compiler's `src/bar.c:12:5: error` opens
+`src/bar.c` at line 12, byte column 5, while a click on `error` finds
+`error`. Drag instead to say exactly what you mean. #key("Enter") and
+#key("Tab") in normal mode look and execute the selection, or the word
+under the cursor. The chords are on the cheatsheet.
+
+= Tags <tags>
+
+There are three kinds, and which directory a command runs in depends on
+which one you click:
+
+#tag("Newcol Joincol Find Grep Help Changelog Tutor Dump Themes Config Debug Exit")
+#tag("New Tty Find Grep Joincol Delcol")
+#tag("Save Tty Collapse Del", path: "/home/me/notes.txt")
+
+- The workspace tag and the column tags run commands in the session's
+ directory (where pardes started). A column's own words (#word("New"),
+ #word("Tty"), #word("Delcol")) act on that column; a pane word
+ (#word("Save"), #word("Del")) acts on the column's pane with the
+ keyboard, or its first; from the workspace tag, on the pane with the
+ keyboard.
+- A pane's tag runs commands in the pane's directory: a file's directory, a
+ terminal's current directory.
+
+A tag is text with undo: type a word into it and click it, or delete the
+defaults. #key(":") moves the keyboard between a body and its tag. A pane
+tag may wrap onto several lines; column and workspace tags are one line.
+The path at the start of a pane's tag is computed: typing into it, or
+clicking it, drafts a new name, #key("Enter") confirms and the next
+#word("Save") writes there; #key("Esc") cancels. #word("Collapse") folds a
+pane to its tag. Unsaved text shows on the grip, the box left of the tag.
+Drag the grip up or down to resize, or onto another column to move the
+pane there.
+
+= The active column and the keyboard <active-column>
+
+Two things are easy to confuse:
+
+- *The pane with the keyboard* is where your keys go.
+- *The active column* is where new panes go. It is the column you last
+ typed in, #btn("B1")-clicked in, dropped a pane into or gave the keyboard
+ to its tag, or the one that got the last new pane. A look does not move
+ it.
+
+They usually agree. Here is how they split. You are typing in column 1, so
+column 1 is active. You click #word("New") in column 2's tag: a scratch
+pane opens in column 2 and takes the keyboard, and column 2 is now
+active. In it you #btn("B3") `x.txt`, which is already open in column 1:
+the keyboard jumps to that pane in column 1, but the active column stays
+2, so the next pane a look opens lands in column 2, away from where you
+are. Type or click in column 1 and it is active again.
+
+== Where new panes go <new-panes>
+
+#word("Placement") picks the rules: `acme` (the default) or `pardes`.
+Under `acme`, a new pane goes into the column whose tag asked, else the
+active column, never into a new column. An empty column it takes whole;
+#word("New") and 9P's #file("pane/new") take the bottom half of the
+column's last pane; a pane opened from a pane's text (a look, #word("Tty"),
+#key("Alt-n")) goes under the pane with the most blank rows, or halves the
+biggest; a command pane goes to the last column. #word("New") in a pane's
+tag opens a `+New` scratch named in that pane's directory, in that pane's
+column; from a column tag, in that column and the session's directory.
+Every new pane but a command pane takes the keyboard. No pane is made
+shorter than its tag and two rows; where there is no room the pane is
+refused.
+
+A column can be empty, as in acme: closing its last pane leaves it, its
+tag over blank space. #word("Delcol") and #word("Joincol") take columns
+away. Closing the session's last pane quits pardes.
+
+= Looking <looking>
+
+#btn("B3") (or #key("Enter")) on a path opens it, or goes to the pane that
+already shows it; `file:12` goes to line 12. The address forms are on the
+cheatsheet. A directory types `ls` into a terminal idle there, else opens
+a terminal there. A URL opens in the browser.
+
+A relative path is looked for where the click was, then where you have
+been: first in the looking pane's own directory, then in the directory of
+each pane on the jump list, most recent first. The first that names a
+file, or a pane open on that path, wins. `./x` and `../x` look only in the
+pane's own directory.
+
+= Command panes <command-panes>
+
+#btn("B2") on a line that is no builtin (`make`, `git log`) runs it with
+the #word("Shell") setting's `-c`, in the directory of the tag or pane it
+came from. In a terminal idle at an empty prompt, a line from that
+terminal's own text is typed into its shell. Anywhere else it runs in a
+command pane, a terminal of its own:
+
+#tag("Kill Save Collapse Del", path: "/home/me/src (make) exit 0")
+
+Its tag says `running`, then `exit N`. The next command for the same
+directory reuses a command pane that has finished (from a column tag, only
+one in that column), below what it showed; a pane still running, or one a
+background job still prints to, is never reused, so a second command
+meanwhile gets a pane of its own. #word("Kill") stops what pardes started
+(`Kill make`: those whose line starts with `make`); #word("Exit") quits
+pardes.
+
+= Unsaved panes <unsaved-panes>
+
+A pane whose text is unsaved is marked on its grip. #word("Del") on it
+refuses once: a notice says `1 unsaved pane — Del again to discard` and the
+pane is listed in `+Unsaved`. The same #word("Del") again, with nothing
+edited since, discards it. #word("Exit"), #word("Restore") and
+#word("Delcol") refuse once over unsaved panes the same way. A `+New`
+scratch under 100 bytes and a command's output never hold anything up.
+
+From the keyboard (#key("SPC d")), #word("Del") on a pane with panes above
+and below it also asks which neighbour takes its rows: #key("k") above,
+#key("j") below, any other key keeps the pane. A click never asks, and
+gives the rows to the pane above.
+
+= Terminals <terminals>
+
+A terminal is a pane like any other.
+
+#tag("Tty+bash Save Mode Filter Collapse Del", path: "/home/me/src")
+
+- `Tty+bash` opens another terminal on that shell; a bare #word("Tty")
+ runs the #word("Shell") setting, `$SHELL` when it is executable, else
+ `/bin/sh`.
+- #word("Save") asks for a path on the pane's notice band and writes the
+ terminal's scrollback there as text; `Save path` writes it at once.
+- #word("Filter") maps the program's colours through the theme.
+- In raw mode Ctrl-V types what you yanked into the program (with nothing
+ yanked, the program gets the key), and Ctrl-Shift-V the desktop
+ clipboard.
+- A program that tracks the mouse (htop, vim with `mouse=a`) gets
+ #btn("B1")'s clicks and drags and the wheel over its grid; #btn("B2") and
+ #btn("B3") stay pardes's. Hold Shift to swap: #btn("B1", shift: true)
+ selects and Shift-wheel scrolls pardes's scrollback, while
+ #btn("B2", shift: true) and #btn("B3", shift: true) go to the program as
+ its buttons 2 and 3. A full-screen program that does not track the mouse
+ gets the wheel as arrow keys. Tags, grips and gutters stay pardes's.
+- `Repl python` in a terminal's tag makes #btn("B2") on a `.py` pane send
+ the text to that REPL instead of running it.
+
+= Reviewing diffs <reviewing-diffs>
+
+Open a `.diff` or `.patch`, or run `git diff` (or `git show`, `diff -u`) as
+a command: once it has finished, output that starts as a diff is shown as
+one, each hunk coloured in its file's language and its added and removed
+rows tinted. Then #btn("B3") to jump, with the usual look resolution:
+
+- a `diff --git`, `---` or `+++` line opens the file (the new one, or the
+ old one on a `---` line unless the `+++` under it names another);
+- a `@@ -a,b +c,d @@` line goes to line `c` of the new file;
+- the `+`, `-` or space in a hunk line's first column goes to that line in
+ the new file (for a removed line, the line now standing where it was);
+- the code after it is ordinary words.
+
+git's `a/` and `b/` prefixes are dropped (and `c/ i/ w/ o/` with
+`diff.mnemonicPrefix`); a `--no-prefix` diff's paths are kept as written.
+
+= pardes FILE and --wait <editor>
+
+In a pane's shell, `pardes FILE` opens FILE in this session and returns at
+once, as acme's `B` does. A FILE not there yet opens an empty pane named
+for it; #word("Save") creates it, making its directories first. Something
+the session refuses (a bad name) is printed and the command exits 1.
+
+`pardes --wait FILE` (`-w`) returns when the pane showing FILE is closed
+(exit 0) or the session goes away (exit 1), as acme's `E` does. Set
+`EDITOR='pardes --wait'` (`GIT_EDITOR` follows it), and `git commit`,
+`crontab -e` and fish's Ctrl-O open in a pane and read the file once you
+close it. Bare `pardes` inside a pane refuses and names `--nested`, which
+starts a separate session whose shells do not forward to it.
+
+= Keys <keys>
+
+Motions select what they cross, and an edit acts on the selection: #key("w")
+then #key("d") deletes a word. #key("x") selects lines, #key("v") extends
+characters, #key(";") collapses to the cursor. #key("s") makes a cursor
+per regex match inside the selection, and every edit then acts at each.
+#key("/") is a case-insensitive substring search, one hit a line; the
+regexes are on #key("s") and #key("S"). #keys("n", "N") step through
+everything a look would open, across panes. Line end is #key("g l"), and
+#key("$") is helix's keep-pipe. #key("SPC") starts the leader,
+#key("SPC ?") lists every path, and #word("Help") lists every key and
+builtin. #word("Tutor") (#key("SPC h t")) practises them.
+
+The language servers run as child processes, one per language when it is
+on `PATH`: `zls`, `rust-analyzer`, `clangd`, `gopls`,
+`typescript-language-server` and `pyright-langserver`
+(`PARDES_LSP_ZIG`, `_RS`, `_C`, `_GO`, `_TS`, `_PY` name another, empty
+turns one off):
+
+#pairs(
+ [#keys("g d", "g D", "g y", "g i", "g r")], [definition, declaration, type, implementation, references; Ctrl-#btn("B1") is a definition too],
+ [#keys("SPC l k", "SPC l r", "SPC l a", "SPC l h")], [hover, rename, code action, select the references],
+ [#keys("SPC l s", "SPC l S", "SPC l d", "SPC l D")], [symbols and diagnostics, of the file and the workspace],
+ [#keys("SPC l c", "SPC l C", "SPC l t", "SPC l T")], [incoming and outgoing calls, supertypes and subtypes],
+ [#keys("] d", "[ d")], [next and previous diagnostic],
+ [#key("=")], [format],
+ [#keys("SPC l i", "SPC l w")], [#word("Lspinfo"): the servers' state; #word("Lspwhy"): why the last query found what it did],
+)
+
+One answer jumps; several open a list where #key("Enter") on a row goes
+there. In insert mode #key("Tab") after a `.` lists the candidate
+declarations and inserts nothing. A format or a rename within the file is
+one undo step; a rename that reaches other files opens a preview instead
+of changing them.
+
+= Sessions <sessions>
+
+```
+pardes --detach=work & a session with no screen of its own
+pardes --attach=work show it here
+pardes-gui --attach=work the SDL window can attach too
+```
+
+The session owns the panes, shells and files; frontends come and go.
+#word("Attach") `work` (#key("SPC s a")) switches this window to that
+session, and #word("Detach") (#key("SPC s D")) leaves it running, shells
+and all. Bare `--detach` names the session after its pid; bare `--attach`
+needs exactly one session. Every attached frontend sees the same screen,
+at the smallest common size. With none attached, `size C R` on the root
+ctl sets the screen and messages clear by the clock. A detached session
+ends when its last pane closes, as any session does.
+
+= Config <config>
+
+#word("Config") (#key("SPC f c")) opens the startup file,
+`~/.config/pardes/init` (`$XDG_CONFIG_HOME/pardes/init` when that is
+absolute; on macOS `~/Library/Application Support/pardes/init`). Each line
+is one builtin, run at start as if executed; `#` starts a comment, and a
+line that fails is skipped silently. Text that is no builtin does not run
+as a shell command.
+
+```
+Theme atelier
+Shell zsh
+Placement pardes
+```
+
+#word("DumpConfig") opens every live setting as the line that sets it, so
+it pastes back into `init` as is. The settings are listed with the root
+ctl in the reference (#doc("fs", section: "settings")). Keys are
+compile-time, in `src/config.zig`.
+
+#word("Dump") writes the workspace to `pardes-<date>-<time>.zon` in
+#word("DumpDir"), and `Restore path` (or `pardes -l dump.zon`) brings it
+back: panes, columns, tags, selections, theme and changed settings; a
+terminal returns with its last MiB of output and a new shell in its old
+directory. Undo history and REPL bindings are not kept. A crash appends
+two lines (build, time, platform, pid; the panic message) to `crashes`
+beside `init`.