# Tags and columns Pardes has three levels of command text: the workspace tag, a tag per column, and each pane's tag. The rule for the workspace and column tags: - A builtin that acts on a pane (`Del`, `Save`, `Undo`) acts on the column's active pane (its first pane when focus comes from another column); from the workspace tag, on the pane with the keyboard. - A column's own words (`New`, `Tty`, `Delcol`) act on that column. - A shell command runs as a command pane of its own, with `run` and `exit` records, in the session's directory (where pardes started), as acme's row and column tags have none of their own. It is never typed into the terminal that has the keyboard. `Tty` starts there too. - Over 9P (`/tagexec`, `col//exec`) there is no click to say which pane is meant, so a pane's word written there is refused, pointing at `pane//ctl`; the tag's own words and shell commands run as above. One run from a pane's tag or text starts in that pane's directory, and a shell command there is typed into the pane when it is a terminal at its prompt. Over 9P the tags are `/tag`, `/col//tag` and `/pane//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: ` () 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 B1 and the wheel; B2 and B3 stay pardes's; Shift swaps each. In raw terminal input, a program that asked for the mouse (xterm's 1000, 1002 or 1003: htop, vim with `mouse=a`, codex) gets B1's clicks and drags and the wheel over its grid, reported in the format it chose and with its modifiers; Shift-B1 selects as ever and Shift-wheel scrolls pardes's scrollback. B2 and B3 execute and look there as in any pane, sweeps and chords included; Shift-B2 and Shift-B3 go to the program as its buttons 2 and 3, the Shift left out. 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/`, or `--- a/` 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: a diff line looks up the path and line it names, as any look does. The hover shows the whole line; the look is of the address it names, exactly as if that text had been selected by hand and right-clicked, with the same resolution (the pane's directory, then the places the jumplist has been), placement and errors. On a `diff --git`, `---` or `+++` line, anywhere on it, markers included, that is the file: `diff --git a/x b/y` and `+++` name the new one, `---` the old one unless the `+++` under it names another (a rename, a new file, `diff -u old/x new/x`), the old name being the one likely gone. A `@@ -a,b +c,d @@` line names `path:c`. On a hunk line, the `+`, `-` or space in its first column names `path:` its new line; for a removed line, 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 9P `look` of a whole line of the diff is the same look. The 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. ## 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.