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
|
# Tags and columns
Pardes has three levels of command text: the workspace tag, a tag per
column, and each pane's tag. A column tag's words act on that column and run
in its active pane (its first pane when focus comes from another column). A
command or `Tty` run from the workspace or a column tag starts in the
session's directory (where pardes started), as acme's row and column tags
have none of their own; one run from a pane's tag or text starts in that
pane's directory. Over 9P the tags are `/tag`, `/col/<n>/tag` and
`/pane/<n>/tag` ([fs.md](fs.md#columns-and-tags)).
## Default words
- Workspace: `Newcol Joincol Find Grep Help Changelog Tutor Dump Themes
Config Debug Exit`.
- Column: `New Tty Find Grep Joincol Delcol`.
- File pane: `Save Tty Collapse Del`; a source file with a grammar adds
`TreeContext`, a result list `LocationsConfig`. PDF: `manual.pdf [1/12]
Tty PdfSections PdfTint Collapse Del`.
- Terminal: `Tty+bash Save Mode Filter Collapse Del`. `Tty+bash` is one word
for `Tty bash`, opening another terminal on that shell (only `Tty` reads a
`+` so). `Mode` cycles raw terminal input, normal mode and insert mode.
- Command pane: `<dir> (<line>) running`, then `exit N`, and `Kill`.
`Undo`, `Redo` and `Mode` (on files) work typed or clicked though they are
not in the default tags. Customized tags keep their text.
A tag word runs as acme's does, in the pane's directory with no file named:
`wc` alone waits on stdin. There is no `$%`; name the file (`wc notes.txt`),
or select the name and middle-click `wc`, which takes a held selection as its
argument.
A program that tracks the mouse gets it; hold Shift for pardes's own. In
raw terminal input, a program that asked for the mouse (xterm's 1000, 1002
or 1003: htop, vim with `mouse=a`, codex) gets the clicks, drags and wheel
over its grid, reported in the format it chose and with its modifiers.
Shift-click selects, executes and looks as ever, and Shift-wheel scrolls
pardes's scrollback. A full-screen program that does not track the mouse
gets the wheel as arrow keys (xterm's alternate scroll, 1007). Tags, grips
and gutters stay pardes's.
`Repl python` in a terminal's tag binds it as that language's REPL
([fs.md](fs.md#repls)). `Repl` takes the languages a code fence names: ada,
bash, c, c_sharp, clojure, cpp, css, elixir, erlang, fortran, go, haskell,
html, java, javascript, json, kotlin, ocaml, markdown, pascal, php,
powershell, python, ruby, rust, scala, typst, zig, and aliases such as `py`
and `sh`.
## Pane builtins
`Collapse` folds a pane to its tagline, giving its rows to the nearest
expanded pane above (else below); again, it takes them back. Its text and
process are kept.
`Del` closes a pane, giving its rows to one neighbour. `Del k` (`DelAbove`)
gives them to the nearest expanded pane above, `Del j` (`DelBelow`) below,
each falling back to the other side. Bare `Del` from the keyboard (`SPC d`),
with expanded panes above and below, asks on the notice band (`k`/Up above,
`j`/Down below, any other key keeps the pane); a click, a 9P write or an
`init` line never asks and gives the rows above.
A pane with unsaved text is refused once: a notice `1 unsaved pane — Del
again to discard`, the pane listed in `+Unsaved`, and over 9P the write
fails (EIO). The same `Del` again, nothing edited since, discards. `Delcol`
refuses a column holding such a pane the same way, without opening
`+Unsaved` or moving focus. `Exit` and `Restore` do the same over the whole
session. A `+New` scratch under 100 bytes is never asked about.
`Edit` runs sam's command language on the body ([fs.md](fs.md#edit)).
`Undo` and `Redo` step the body through its last 256 edits, as `u` and `U`.
Unsaved text shows on the pane's grip, as acme's modbutton, not in the tag.
In a terminal the grip is two cells: the pane's mode (blank normal, `^`
insert, `$` tty mode), then `*` while unsaved.
## Reviewing diffs
Open a `.diff` or `.patch` file, or run `git diff` (or `git show`, `diff -u
old new`) as a command from any tag: once the command has finished, output
that starts as a diff does (a `diff --git` line, or a `--- ` line with `+++
` and `@@` under it) is shown as one. Each hunk's code is coloured in the language of the file its
section names (`+++ b/<path>`, or `--- a/<path>` for a deleted file), its
old side (context and removed lines) and new side (context and added lines)
each parsed as one text, so a string or comment across lines colours as it
does in the file. Added and removed rows are tinted to the pane's edge,
their `+`/`-` in the tint's hue (the theme's ANSI green and red where it
has them); a file in no language pardes knows keeps the plain line colours.
Only the hunks in view are parsed, a few dozen lines at a time, each once.
Then right-click to jump; the look's hover shows what the click takes. On
a `diff --git`, `---` or `+++` line, anywhere on it, markers included, that
is the whole line, and it opens its file: `diff --git a/x b/y` and `+++`
the new one, `---` the old one unless the `+++` under it names another (a
rename, a new file, `diff -u old/x new/x`), since the old name is the one
likely gone. On a `@@ -a,b +c,d @@` line it is the whole line again, and
opens the new file at line c. On a hunk line, the `+`, `-` or space in its
first column takes the whole line and opens the new file at that line; for
a removed line, at the new line now standing where it was (the one after
it, or the hunk's last when it went from the end of the file). The code
after it is words, looked at as ever.
A path is the repository's name for the file. In a git section (one with a
`diff --git` line) git's side prefix is dropped when both paths on that
line carry one, different ones: `a/`/`b/`, or with `diff.mnemonicPrefix`
`c/`, `i/`, `w/`, `o/`. `--no-prefix` writes none, so there `a/x a/x` is a
real directory `a`, kept. A plain `diff -u`'s names are used as written,
past the timestamp. The file is looked for from the repository's root
(pardes walks up from the diff's directory, a command pane's own, to a
`.git` or `.jj`), else from that directory. A file that is not here (a
branch not checked out) opens nothing and says so by that name: `Look:
src/x.zig: no such file here`, or `deleted by this diff` for a deleted one.
A 9P `look` of a whole line of the diff does the same.
## Editing tags
A tag is text like a body, with the body's normal and insert modes and undo.
A pane tag may hold several lines and wraps, taking a row per shown line up
to eight and leaving its body at least one; a collapsed pane shows the first.
Up on its first row in insert mode (or Alt-Up in either mode) folds a tag to
one row, Down on its last (Alt-Down) unfolds it. Column and workspace tags are
one line: a newline typed, pasted or written into one becomes a space.
The path (and a PDF's page) at the start of a pane tag is computed and
read-only; `0` goes to its start, and motions select and yank across it.
Typing into a file's path, or clicking it, starts a draft of a new name:
Enter or Tab confirms it, Escape or leaving the pane cancels. Confirming
changes the buffer's save target and marks it unsaved; nothing on disk is
renamed until `Save`. A pane-tag command confirms a valid draft first.
Left-click a tag to type at the click, in insert mode. Esc is normal mode:
there Tab executes the word under the cursor (or the selection); Enter looks
it up in a pane's tag and runs it in a column or workspace tag. Executing
gives the keyboard back to the body first. Paste goes to the focused tag.
`:` in a body's normal mode focuses its tag (the first time, on `Save`); `:`
in a tag goes back. The window keys (`Ctrl-w`, `SPC w` with `h/j/k/l`) move
between panes; up from the top pane reaches its column's tag, then the
workspace's, and Left/Right walk the column tags. Search, `s`/`S`, pipe and
Save's path prompt get a line on the pane's notice band; in a tag `s`, `S`
and `|` act on the tag's own text, while `/` searches the body.
## Moving and resizing
Drag a pane's grip up or down its column and its top follows, the pane
above giving or taking rows, down to its tag alone; drop it in another
column and it moves there. In the GUI the 2 px rule between panes drags too.
A column's right edge drags its width. Drag a column's grip past a
neighbour's middle to move the whole column there; short of that it moves
the column's left edge.
A terminal keeps its tag and 2 body rows: no drag, squeeze or smaller
window takes it below that, and `pty/ctl`'s `winsize` gives a pty 2 rows at
least. A text pane can be dragged down to its tag.
## Empty columns
A column can hold no pane, as acme's can: its tag stands over blank space in
the theme's `empty_col` colour. `Newcol` makes one right of the keyboard's
and gives its tag the keyboard. Closing a column's last pane leaves the
column empty, the keyboard on its tag. Only `Delcol` and `Joincol` take a
column away; `Joincol` keeps the right column's tag, its panes below. A pane
dragged onto an empty column fills it. `Delcol` of the last column leaves
the workspace tag alone; `Newcol` or `New` starts again. Unlike acme, pardes
quits when the session's last pane closes.
## Where new panes go
Every new pane goes through one placement, chosen by `Placement acme` (the
default) or `Placement pardes` (bare flips it; `SPC c p`).
No placement leaves a pane shorter than its tag and 2 body rows. Where the
chosen place has not that room, the column's tallest pane is halved; where
no one pane can give it but the column holds every pane's minimum with the
new one's, the rows are shared out again; otherwise the pane is refused,
`no space for a pane in that column: each keeps its tag and 2 rows` (ENOSPC
over 9P). A pane alone in its column always fits.
`Placement acme` is acme's makenewwindow. The active column is the one last
typed or clicked in, dropped into, whose tag was given the keyboard, or that
was given the last new pane; a Look moves the keyboard, not the active
column. A new pane goes into the column whose tag the command came from,
else the active column, never into a new column:
- an empty column it takes whole;
- from a tag, or 9P's `pane/new`, it takes the bottom half of the column's
last pane;
- from a pane's text (a Look, `Tty`, `Alt-n`, a Grep or Find listing), it
goes under the text of the pane with the most blank rows when that is
more than 15 rows, or more than 3 and more than half the biggest pane;
otherwise it halves the biggest pane, or the asking pane when that is in
the column and not much smaller;
- `New` goes to the bottom half of its own column's last pane;
- a command pane or `+Errors` pane goes to the last column's last pane (a
command from a column's tag to that column, reusing a finished command
pane only there). With no room anywhere, `+Errors` text is logged as `msg`
records.
`Placement pardes`: an empty column whose tag asked, or has the keyboard, is
filled; a scratch goes under the pane that asked; a shell under it or the
nearest pane with room; a document beside the last one read, or in a column
of its own on the left when there is none and the column is at least 200
cells wide; a command pane at the foot of the last column.
## Saved workspaces
`Dump` and `Restore` keep workspace and column tags (empty ones too) and
empty columns ([config.md](config.md#dumps)). The column row stays above
the panes with `Tagbottom` on; on screens under three rows it is left out.
|