# Editable tags
Pardes has three levels of command text: the workspace tag, one tag per
column, and each pane's tag. Column commands act on that column and run in
its active pane (or its first pane when focus comes from another column); a
column with no pane is described under [empty columns](#empty-columns). This makes
`New`, `Tty`, `Find`, and `Grep` available beside the work they act on.
A command or a `Tty` run from the workspace tag or a column tag starts in
the session's directory, where pardes was started, as acme's row and column
tags have no directory of their own; one run from a pane's tag or text
starts in that pane's directory.
`New` appears only in the column tag by default; pane tags keep their own
save, terminal, close, and collapse commands. `Tty` opens a new embedded terminal.
In a terminal's own tag the word names the shell it runs, `Tty+fish`, tinted
with the tag's name colour: `Tty+arg` is one word a tag can hold for `Tty
arg`, so clicking it opens another terminal on that shell, as `Tty fish`
would. Only a builtin that declares `plus_arg` reads a `+` so; `Tty` is the
one, since other arguments (a dump's name) may contain `+`. A command pane's tag reads `
() running` or `exit N`
and offers `Kill`. `Repl python` in a terminal's tag binds it as Python's
REPL, its id, `python-a`, beside the Tty word: a middle click or the execute
key on a `.py` body then types the text into it rather than running it, and
several bound ask which. `Repl` takes any language a code fence names
(`py`, `Python`, `sh`): 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;
an unknown one is refused, naming a few of these. The tag's own words, `Exec ` by name and a
command word @`cmd` still run as commands (docs/fs.md).
A tag word runs as acme's does, in the pane's directory with no file named:
`wc` alone waits on its stdin. pardes has no `$%` for the pane's file; name
it (`wc notes.txt`), or select the name and middle-click `wc`, which takes a
held selection as its argument.
Pane and column command text leave a small gap after their aligned drag grips.
GUI pane mode symbols are centered by their visible ink; changing the font or
its size refreshes the cached measurements.
The column grip has a different
color from a pane grip. It stays blank and muted even when its column is active,
and lights in its full accent while it is held.
Drag it past a neighbour's middle to move the whole column there; dropped short
of that, it moves the column's left edge instead, as a border drag would. While
it is held, a dashed rail in the grip's accent stands where the column's left
edge will land, beside the rule as a border drag's rail does. Only columns
between the old and new positions shift. Each column keeps its width, panes and
command text.
Two panes in a column are resized as acme's windows are, by the grip: drag
a pane's grip up or down its own column and its top follows, the pane above
taking or giving the rows, either one down to its tag alone (acme's
coldragwin keeps a window its tag line); drop it in another column and the
pane moves there. In the GUI the 2 px rule between two panes also drags
their seam. No row of text is a handle: a pane's last row takes a click like
any other, and a terminal, which draws no rule, resizes by the grip. A
column's right edge still drags its width.
When Look opens the first document and its source column is too narrow for
a new column, it splits below the originating pane, just like `Tty`, instead
of inserting at the top of the leftmost column. The originating terminal is
kept. As with `Tty`, a tagline-only source uses a roomier split parent.
`Collapse` reduces a pane to just its tagline, giving all its body space to
the nearest expanded pane above, or below if none is above. Other panes keep
their heights. Execute it again to reclaim its former height from that one
neighbor, as far as available space allows. If every pane is collapsed, the
unused area stays blank.
Its text and terminal process are kept;
the command stays available in the visible tag. Every default pane tag includes
`Collapse`, including file, terminal, image, and PDF panes.
`Edit` is acme's: the rest of the line is sam's command language, run on
the pane's body (`Edit ,x/foo/c/bar/` renames every `foo`), from a tag, a
pane's `ctl` or `exec`. Addresses are the `addr` file's, `line:col`
included; the commands are `x y g v c a i d s p = m t`, `u` alone, and `{ }`
with a command per line. All its changes are one undo step, applied only
if every command ran; an error says why in acme's words and changes
nothing. `p` and `=` print to the directory's `+Errors`. Left out: the file
commands `b B D e r w f X Y`, the pipes `< | >`, and `\1`-`\9` in `s`,
since mvzr keeps no submatches; acme applies changes that come out of
sequence with a warning, pardes refuses the Edit. In `s`, `&` in the
replacement is the matched text (`\&` a plain `&`); in `c`, `a` and `i` an
`&` is only an `&`, as in sam. A pattern that finds nothing says so with the
pattern (`no match for regexp /nomatch/`), and an `s` on an empty dot says
`no substitution: dot is empty`. A loop that finds nothing is no error, as
in sam: `Edit ,x/zzz/c/bar/` with no `zzz` changes nothing and succeeds,
silent, where `,s/zzz/bar/` says `no substitution`.
`Undo` and `Redo` are acme's: typed or clicked in a pane's tag, or written
to its `ctl`, they step the body back and forward through its edits, as the
`u` and `U` keys do. They are not in the default tags.
`Del` closes a pane and gives its rows to one neighbor; the rest of the
column keeps its heights. A pane with unsaved text is refused once, as
acme's Del warns (exec.c del, wind.c winclean): a short notice, `1 unsaved
pane — Del again to discard`, the pane listed in a kept `+Unsaved` (`:
Modified`, then `Del again to discard`), and the same `Del` again, nothing edited since, closes it and
throws the text away; `Delcol` refuses a column holding such a pane the same
way (exec.c delcol), but changes nothing else in refusing -- no `+Unsaved`
opens, no focus moves; its `unsaved` records and notice say which. Each word warns on its own, from a key, a tag, `exec`
or a ctl, where the refusal fails the write with EIO. `Del k` (or `DelAbove`) gives them to the nearest
expanded pane above, `Del j` (or `DelBelow`) to the one below, each falling
back to the other side. Bare `Del` from the keyboard (`SPC d`, or Enter on
the word) on a pane with expanded panes both above and below asks on the
pane's notice band: `k` or Up gives the rows above, `j` or Down below, and
any other key keeps the pane. A click, a 9P write or a startup line never
asks; there bare `Del` gives the rows to the nearest document above, as it
always has. A collapsed pane is never asked about, and collapsed neighbors
are passed over: they only keep a weight for later.
A tag is a text like a pane's body: pane tags, column tags and the
workspace tag all edit with the body's own normal and insert modes, undo
included. A pane's tag may hold more than one line, and a line wider than
the pane wraps onto more rows, as acme's tag does: it takes a row per shown
line, up to eight, and leaves its body at least one row. A line exactly as
wide as the pane stays one row, its caret at the tag's edge past the last
character, as acme's tick is (in a terminal, on the last cell). A word the
wrap breaks across rows is still one word to a click. A collapsed pane shows
only the first row.
A pane tag starts expanded, showing all its rows, and can be collapsed to
one row, as acme's Tagup does. In the tag's insert mode Up on its first row
collapses it and Down on its last row expands it; Alt-Up and Alt-Down do
the same in either mode. acme expands or collapses on any arrow key typed in
the tag (Up collapses, the others expand); here arrows keep moving the
cursor, and only these keys at the tag's edges change its height. The column and workspace tags
are one line, as acme's (cols.c:244 gives a column tag one font height): a
newline typed, pasted or written into one becomes a space, and a dump that
holds a column or workspace tag of several lines, from before, comes back
with its lines joined by spaces. The path and a PDF's page at the start of a
pane tag are computed, never stored, and read-only. The keyboard reaches
them as the mouse does: `0` goes to the line's start, the path's, as in
acme, and motions select and yank across the path and the commands. An edit
that would change them is refused and leaves the cursor where it was; typing
into a file's path instead drafts a new name, as clicking it does. When they
grow or shrink (a rename, a PDF's page) the cursor keeps
its place in the text after them.
Left-click a tag or a header to type into it at the click, in insert mode.
A pane tag wraps instead of scrolling sideways; a column or workspace tag
reveals the caret horizontally when its text is wider than its column.
Esc is normal mode, where everything a body's normal mode does works. There
Tab executes the word under the cursor (or an explicit selection), and Enter
looks it up in a pane's tag but runs it in a column or workspace tag, whose
words are all commands; in insert mode Enter is a new line. Executing gives
the keyboard back to the body first, so `Del`, `Kill` and `Restore` never return into a tag that is gone.
Pasted text goes to the focused tag, not to the file or embedded shell
beneath it.
`:` is the one key a tag and a body do not share: in the body's normal mode
it focuses the pane's tag in normal mode, and in the tag's normal mode it
goes back to the body; in a column or workspace tag it goes back to the
active pane. Each pane, column and workspace tag remembers its own cursor
during the session; the first `:` into a pane tag starts on its `Save`. A
tag's text changing under it (a 9P write, a shorter tag) pulls the cursor
back inside it.
Moving between tags is the window keys' job, as it is between bodies
(`Ctrl-w` or `SPC w` with `h/j/k/l`): they move to the neighbouring pane's
body. Up from a pane with nothing above it reaches its column's tag, then
the workspace's; Down comes back the same way, and Left and Right walk the
column tags.
Search (`/`), `s`/`S`, pipe (`|`) and Save's path prompt are not typed into
the tag: each gets a line of its own on the pane's notice band, with the
body's insert-mode keys. Pressed in a tag, `s`, `S` and `|` answer for the
tag's own text, as they do for a body, and a header's go on the active pane's
band; `/` searches the body wherever it is pressed, as acme's Look from a tag
does.
Pane filenames and commands now have a single separator space rather than
generated right-alignment padding. Intentionally customized spacing is kept.
## File names
Clicking a file pane's name, or typing into it from the tag, starts a draft
of it, typed into where it was clicked or typed.
Enter or Tab confirms the new buffer name; Escape or leaving the pane
cancels the draft. Confirmation changes the
buffer's save target and marks it unsaved. It does **not** rename, create or
overwrite a disk file. A subsequent explicit `Save` writes the buffer to its
committed name. Executing a pane-tag command confirms a valid name draft
first, so a visible draft cannot silently save to the previous name.
Terminal working directories and generated image/PDF status remain managed
by their corresponding commands. Their command tails are editable just like
file command tails.
PDF tags follow the same filename-first layout: `manual.pdf [1/12] Tty Del
PdfSections PdfTint Collapse`. Sections and tint commands remain in the editable
tail, without displaying the current tint state. `PdfFit` (`SPC t z`) remains
available, as do the shortcuts for `PdfTint` (`SPC t i`) and `PdfSections`
(`SPC t s`, or `f` on a PDF).
Terminal tags include `Mode`, which cycles through raw terminal input, normal
editor mode, insert mode, and back to terminal input. On files and text output
panes, `Mode` cycles between normal and insert mode; it is available as a command
but does not appear in their default tags. Images and PDFs keep their normal mode.
Executing `Mode` from a tag leaves the tag and advances the parked body mode.
Ctrl-B keeps its terminal/editor toggle. Existing custom tags can still use
`Togglettymode` for that two-way terminal toggle. Old default terminal tags
upgrade to `Mode`; customized command text is preserved.
## Saved workspaces
`Dump` and `Restore` preserve customized workspace and column tags, including
intentionally empty tags, and columns that hold no pane. New columns start with the standard column tag.
Closing a column keeps surviving columns' tags; `Joincol` keeps the destination
column's tag. Old dumps without these optional fields retain the defaults.
The automatic `Restore` shortcut does not overwrite a customized workspace
tag.
The column row stays above panes with `TagBottom` enabled. On screens shorter
than three rows it is omitted so a pane still has room. SDL and TTY share the
same tag text, editing and layout; SDL additionally uses compact font sizing
and subtle pixel separators.
The column row is always shown. An old `ColumnTags` line in an init file is
ignored, with a message saying so.
`FocusTint` controls active-column and active-pane emphasis. SDL also honors
the shared bold, underline, and strikethrough attributes, including diagnostic
underlines and the optional `SyntaxBold` keyword weight.
Unsaved text shows on the pane's grip button, as acme's modbutton does,
not in the tag: the tag names the file and nothing more. In a terminal the
grip is two cells: the second is `*` while the pane holds unsaved text, and
the first is the pane's mode: blank in normal mode, `^` in insert, `$` when
the keyboard goes to a terminal's program (tty mode). The `dirty` file
and `index`'s flag say the same to a script.
## 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, white in the acme theme as acme paints it
(cols.c:186-188), and the frame's border fill in themes that do not set it. `Newcol` makes an
empty column right of the keyboard's and gives its tag the keyboard. Closing a
column's last pane (`Del`, `Del k`/`Del j`, a shell exiting, a drag to another
column) leaves the column empty where it was, and the keyboard goes to its tag
if it was on that pane. Only `Delcol` and `Joincol` take a column away.
`Delcol` and `Joincol` from a column's tag act on that column; `Delcol`
written to a pane's ctl closes that pane's column. A pane dragged onto an
empty column fills it.
## Where new panes go
Every new pane goes through one placement, chosen by the `Placement` setting:
`acme` (the default) or `pardes`. `Placement pardes` or `Placement acme` sets
it, in an init file, a tag or the root ctl; bare `Placement` flips it; `SPC c
p` is its leader path, and `Config` reports it.
Under either, no placement leaves a pane, new or split, shorter than its tag
and two body rows (acme's minht keeps one). Where the place chosen has not
that room, the column's tallest pane is halved instead; where no one pane
can give it but the column's rows hold every pane's tag and two rows with
the new one's, the rows are shared out again, each at least its minimum;
only when they do not -- the arithmetic, not the halving, decides -- is
the new pane refused and closed, with `no space for a
pane in that column: each keeps its tag and 2 rows` (a 9P write or open of
`pane/new` fails with it, ENOSPC). A pane alone in its column always fits.
After placement a terminal keeps that floor too: no drag of a grip, no
squeeze of its column by the others' weights and no smaller window takes
it below its tag and two body rows (a one-row terminal loses its prompt's
mark and would read busy for ever); its neighbours give the rows, and only
a window too short for every floor leaves it less. A text pane keeps
acme's way and can be dragged down to its tag alone; acme has no
terminals to follow here. A folded terminal (Collapse) is a tag by choice.
`pty/ctl`'s `winsize` likewise gives a pty two rows at least.
A `+Errors` pane goes to any column with room, the last first; with none,
what it would have shown (an Edit's `p` or `=`, a write to `errors`) is
logged as `msg` records, a line each, and the Edit still succeeds.
`Placement acme` is acme's makenewwindow (util.c:449-495). The core keeps
acme's *active column* (activecol, dat.c:37): the column last typed in
(acme.c:487), clicked in with the select button (acme.c:659), dropped into by
a grip (acme.c:640), whose tag was given the keyboard (`Newcol`, an emptied
column, `Ctrl-w k`), or that was given the last new pane (util.c:467). A Look
click moves the keyboard but not the active column, as button 3 does not in
acme. A new pane goes into the column a command's tag belongs to when it came
from a column tag, else the active column, else the keyboard's pane's, and
never into a new column:
- an empty column it takes whole (util.c:468-469);
- from a tag, or 9P's `pane/new` (acme's `t->w == nil`), it takes the bottom
half of the column's last pane (coladd, cols.c:62-65);
- from a pane's text (a Look, `Tty`, `Alt-n`, a Grep or Find listing), it goes
right 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
(util.c:482-486); otherwise it halves the biggest pane, or the asking pane
when that is in the column and not much smaller (util.c:487-491);
- `New` goes into its own column, the bottom half of its last pane
(look.c:921-923);
- a command pane or a `+Errors` pane goes to the last column, the bottom
half of its last pane (util.c:94-98); a command run from a column's tag
goes to that column instead, and reuses a finished command pane only in
that column.
`Placement pardes` is what pardes did before: an empty column whose tag asked,
or has the keyboard, is filled; a scratch goes right 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.
`BootShell replace` brings back one more placeholder: a document dragged into
the left column closes the column's lone shell if nobody has typed into it.
`BootShell keep`, the default, never closes a pane for another one.
Down from an empty column's tag stays there, and the pane-to-pane keys pass
over an empty column; Left and Right from a tag walk every column's tag.
`Delcol` of the last column does as acme's does: the column goes and the
window stays, empty but for the workspace tag, where `Newcol` (or `New`,
which makes the column it goes in) starts it again. One divergence from
acme remains: acme keeps running when its last window closes; pardes quits
when the session's last pane closes by `Del`, a shell exiting or the like.