summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/config.md38
-rw-r--r--docs/effects.md80
-rw-r--r--docs/fs.md9
-rw-r--r--docs/helix-keys.md2
-rw-r--r--docs/tags.md73
-rw-r--r--docs/themes.md7
-rw-r--r--docs/ui-review.md3
7 files changed, 197 insertions, 15 deletions
diff --git a/docs/config.md b/docs/config.md
index cd719fd3..0332d854 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -111,9 +111,16 @@ themes and all imported names remain available.
`FocusTint` toggles the focused pane and column tag tints; it is on by default.
Workspace, column and pane command text can be edited directly; see
[editable tags](tags.md) for naming and saved-workspace behavior.
-`ColumnTags` toggles the column command row in both GUI and TTY; it is on by
-default. Add `ColumnTags` to startup configuration to reclaim that row on a
-compact screen. Hiding it preserves your custom column commands.
+The column command row is always shown; an old `ColumnTags` init line is
+ignored with a message.
+`Placement acme` (the default) puts new panes where acme would, in the active
+column; `Placement pardes` brings back pardes's own rules, which open a first
+document in a column of its own. See [where new panes go](tags.md#where-new-panes-go).
+`BootShell keep` (the default) leaves a shell alone when a document is dragged
+into the left column beside it, whatever it holds; `BootShell replace` closes
+such a shell there when it is the column's only one and nobody has typed
+into it (no scrollback, cursor still on the first prompt line), the boot's
+placeholder giving its rows to the document. Bare `BootShell` flips it.
`Verbose` toggles the message-row announcement every builtin makes of its own
name before it runs; it is on by default, and the builtins that own the message
row themselves (`Msg`) never announce. Turning it off leaves the row to the
@@ -314,9 +321,11 @@ name, thirteen required RGB roles (`sel_bg`, `sel_fg`, `tag_bg`, `tag_fg`,
`box`, `box_dim`, `kw`, `str`, `num`, `comment`, `lineno`, `scroll_track`,
`scroll_thumb`), nullable `bg`/`fg`, and either a 16-color RGB `palette` or
`null`. Optional nullable RGB roles extend this format:
-`tag_active_bg`, `tag_active_fg`, `tag_name_fg`, `tag_active_name_fg`, `border`, `lineno_active`, `search_bg`, `search_fg`,
-`diagnostic_error`, `diagnostic_warning`, `diagnostic_info`, and
-`diagnostic_hint`. Missing new roles use backward-compatible defaults, so
+`tag_active_bg`, `tag_active_fg`, `tag_name_fg`, `tag_active_name_fg`, `border`, `empty_col`, `lineno_active`, `search_bg`, `search_fg`,
+`diagnostic_error`, `diagnostic_warning`, `diagnostic_info`,
+`diagnostic_hint`, `tag_sel_bg`, `tag_rule`, `box_border` and `box_dirty`;
+`sweep_bg` and `sweep_fg` take three triples, and `rule_px` and `rail_px` a
+pixel count. Missing new roles use backward-compatible defaults, so
previously exported files remain valid. [Theme customization](themes.md)
describes each role and its fallback. RGB values are three-byte arrays, and
hex literals are accepted. The original fields remain required; there is no
@@ -527,6 +536,23 @@ the chain empty the pass is bypassed. CRT works in linear light with restrained
scanlines, mask, bloom and vignette, and no curvature, so clicks land where
they are drawn.
+The focused pane can stand off the page (SDL GUI, off by default):
+
+```text
+Lift shadow a soft drop shadow, on the other panes' bodies only
+Lift rim a hairline just above the focused tag (light, or shade on a light page)
+Lift auto a shadow on a light page; on a dark one the others recede
+Lift off
+InactiveDim 30 the unfocused panes' text fades 30% toward its ground
+Motion smooth off, crisp, smooth (the default), bouncy or playful
+GripWidth 150 the grip's button and the scrollbar under it, percent of the
+ theme's rail_px (12px at a 17px tagline; 50 to 300)
+```
+
+`InactiveDim` works everywhere (a grid shows it at once) and never takes a
+pair below its own contrast or 4.5. Under `Lift auto` on a dark page it is 30
+while unset. `Motion` sets how every such effect moves: see docs/effects.md.
+
`EffectCode PanelAscii` or `EffectCode Crt` lists the current backend's
build-embedded source paths under `/virtual`. Look opens each full file;
no checkout is needed, but the build must carry them (`-Dembed-sources=true`,
diff --git a/docs/effects.md b/docs/effects.md
new file mode 100644
index 00000000..3f375b7d
--- /dev/null
+++ b/docs/effects.md
@@ -0,0 +1,80 @@
+# Effects: feel reviews
+
+**The rule above all the others:** no effect may alter or cover a focus
+indicator (the focused pane's tag colour, its grip, the cursor, the
+selection) or reduce its contrast. The effects are sugar; the indicators are
+how a person knows where they are. Every G stage is reviewed against this.
+Lift, for one, falls only on pane bodies and rails, never on a tag, a grip or
+a header, and its strength is capped so text and the selection keep min(their
+contrast, 4.5) (tests in src/gui/gui.zig). The rule binds effects, not a
+theme's structure: the rules between panes (2px, `rule_px`) are the theme's
+borders, and the one over a tag band stays in the band's slack, never over
+its text. A dim touches only the unfocused
+panes, with the same floor, and the focused pane's text is never at less
+contrast than theirs (tests in src/draw.zig).
+
+Each effect of docs/render-pipeline.md §9 lands behind its own switch, off,
+and is kept only after a feel review (§8.4): a frame series on the virtual
+clock, a recording, and a verdict — keep, polish or drop — with one line of
+why. The verdict is the user's.
+
+| effect | switch | state | review material | verdict |
+|---|---|---|---|---|
+| Crt (bundled post pass) | `Crt 0..3` | kept, rewritten (no barrel) | fx-compare stills, live window | kept at the user's live look |
+| Ripple, Glitch | — | removed | live window | dropped by the user after a live look |
+| G1 lift | `Lift shadow\|rim\|auto` (off), `InactiveDim <percent>` | opt-in until the focus-lift default is decided | lift-shots-2 (off, shadow, rim, auto on acme, dusk, forge); frame series + mp4 per Motion flavour | shadow on acme: keep as is. Round 1 dropped glow and surface (surface lowered the focused text's contrast) and made rim a hairline just above the focused tag (light on a dark page, shade on a light one). auto on a dark page recedes the others (InactiveDim 30) |
+
+## Motion flavours
+
+`Motion off|crisp|smooth|bouncy|playful` (default smooth, tuned so arrivals
+land inside §8.1's 220 ms; bouncy and playful run longer, opt-in) is one parameter set
+(animation.Motion) every fx animation reads, so a flavour is data, not a
+branch in each effect. Input is never blocked, and a new target always
+retargets from the current position and velocity.
+
+| flavour | timing (ω, length) | follow-through (ζ) | anticipation | squash/stretch | exaggeration (gain) | secondary lag | arcs |
+|---|---|---|---|---|---|---|---|
+| off | instant | — | — | — | — | — | — |
+| crisp | 60, 0.6× (leaves at full speed) | 1 (none) | — | — | 1 | in step | — |
+| smooth | 34, 1.1× (slow in, slow out; ≤220 ms) | 1 (none) | — | — | 1 | 0.85 | 0.04 |
+| bouncy | 24, 1.4× | 0.35 (overshoots ~30%, settles twice) | — | 0.15 | 1.25 | 0.8 | 0.08 |
+| playful | 18, 1.7× | 0.28 (overshoots ~40%) | 0.15 of the move | 0.35 | 1.4 | 0.55 | 0.15 |
+
+The flavours are distinct by design, not tuning: crisp leaves at full speed
+and never passes its mark; smooth takes twice as long and eases in and out; bouncy clearly passes its mark and settles back once or twice;
+playful winds up the other way first, flies well past, and stretches along
+its path and squashes as it lands, its text with it (the user's choice); a
+pointer inverts the same stretched box, and landed, a pane is exactly its
+target. A motion only a few pixels big (Lift) is
+exaggerated by the flavour's gain so its character shows. The flavours drive
+the Lift spring (time-based), the notice drop and the pane moves (PanelSlide,
+PanelZoom, PanelVertical opening or moving, whose length scales with the
+flavour); a closing pane keeps its effect's own exit. Chart and side-by-side
+video: .scratch/render/motion/compare/.
+
+Which principles each motion uses:
+
+- **Lift** (G1): timing, slow in / slow out (the spring), follow-through
+ (bouncy and playful lift past full and settle back), anticipation (playful
+ dips before it rises; below zero nothing is drawn, so it reads as a beat
+ before the lift), staging (only the focused pane lifts; nothing else moves
+ with a focus change), exaggeration (the flavour's gain). Squash, stretch,
+ arcs and secondary lag have nothing to act on in a lift.
+- **Notice drop and pane moves**: timing and follow-through from the flavour's
+ spring over the move's length; anticipation (playful). A pane past its mark
+ never takes a neighbour's click, a rising one stays in its box, and a notice
+ past its row stays in its pane's body.
+- **Cursor** (G3, next): designed around the same set: glide on the spring,
+ stretch along the path, an arc on long jumps, the trailing corners as the
+ secondary action.
+
+
+Notes on G1: the lift and the dim run on one focus spring per pane, at the
+Motion flavour's pace, sampled at each frame's own time; while it moves the
+GUI draws at the display's rate, and a grid snaps. A notice floats on a lift
+of 1 while a shadow or rim is on. InactiveDim under `Lift auto` defaults to
+30. The fade is in linear light, so on a dark page it is gentle: at 30
+forge's text goes from 15.5:1 to 11.2:1 and dusk's from 6.4:1 to 4.8:1,
+plainly quieter and still easy reading; at 10 forge barely moves (14.1:1).
+On a light page the same percent bites far harder (acme: 7.0:1 at 10, the
+4.5 floor at 30), which is why `auto` shades there instead of dimming.
diff --git a/docs/fs.md b/docs/fs.md
index c4bdac1b..45b04675 100644
--- a/docs/fs.md
+++ b/docs/fs.md
@@ -71,8 +71,13 @@ for any process, and `$NINE_MOUNT/pardes/NAME/` a `--detach=NAME` session's.
9ns exports `$NINE_MOUNT` to everything it starts, so a script checks that
variable to know the mount is there, and takes the name from `$PARDES_9P`
(`pardes-9p-<pid or NAME>.sock`). A new pane made through `pane/new` is a scratch named
-`<dir>/+New` until it is given a name, and closing a column's last pane
-leaves such a `+New` in its place (`Delcol` closes the column).
+`<dir>/+New` until it is given a name. A column may hold no pane, as in acme:
+`Newcol` makes one empty, and closing a column's last pane leaves it empty
+with its tag holding the keyboard (`focus` reads empty) and logs only the
+`del`. `pane/new` places its pane as acme's makenewwindow(nil) does: in the
+active column, filling it when it is empty, else taking the bottom half of its
+last pane ([where new panes go](tags.md#where-new-panes-go)). `Delcol` closes the column. Closing the
+session's last pane quits pardes; see [tags](tags.md#empty-columns).
For [Linux v9fs](https://www.kernel.org/doc/html/latest/filesystems/9p.html),
use `version=9p2000,cache=none,access=any` and `trans=unix`, or `trans=tcp`
diff --git a/docs/helix-keys.md b/docs/helix-keys.md
index c703a3da..8874bf08 100644
--- a/docs/helix-keys.md
+++ b/docs/helix-keys.md
@@ -127,7 +127,7 @@ language-backend queries, and the shell pipe.
| `Enter` (normal) | acme **look** chord: EXPLICIT selection, else file-ish word under cursor | pardes-specific, keep (helix normal-mode Enter unbound). Covers helix `gf`. Implicit motion residue falls back to the cursor word | pardes-specific |
| `Tab` (normal) | acme **execute** chord | pardes-specific, keep; explicit-selection rule as Enter | pardes-specific |
| `:` (normal, body or tag) | in the body, focuses the pane's tag in normal mode at its remembered cursor (the first time, on `Save`); in the tag, goes back to the body; in a column or workspace tag, back to the active pane. The tag's normal and insert modes ARE the body's: every motion, selection, edit and undo works there, and `0` goes to the line's start, the path's. Tab runs the word under the cursor or the selection and Enter looks it up (in a column or workspace tag Enter runs it too), and either hands the keyboard back to the body first. Clicks choose a new cursor position and type into the tag. | Each tag keeps its own cursor during the session. The computed path/marker/page is reachable and yankable but read-only: an edit into it is refused, and typing into a file's path drafts a new name. File-name changes are staged as described in [editable tags](tags.md). | pardes-specific |
-| `Ctrl-w k` / `SPC w k` (pane with nothing above) | focuses its column's tag, then the workspace tag; with `ColumnTags` disabled it goes directly to the workspace. `Ctrl-w j` walks back to the panes, `Ctrl-w h`/`l` walk the column tags. Headers edit exactly as a pane tag does. | Column commands target that column's active pane, or its first pane when coming from elsewhere. Workspace and column text are independently editable and persist in dumps. See [editable tags](tags.md). | pardes-specific |
+| `Ctrl-w k` / `SPC w k` (pane with nothing above) | focuses its column's tag, then the workspace tag. `Ctrl-w j` walks back to the panes, `Ctrl-w h`/`l` walk the column tags. Headers edit exactly as a pane tag does. | Column commands target that column's active pane, or its first pane when coming from elsewhere. Workspace and column text are independently editable and persist in dumps. See [editable tags](tags.md). | pardes-specific |
| `Ctrl-w` + `h/j/k/l`/arrows | directional pane focus prefix — editor normal mode only | pardes' own window handling (helix window mode skipped, section C). Runs the SAME `Left`/`Down`/`Up`/`Right` builtins `SPC w h/j/k/l` runs; Raw **tty** mode forwards Ctrl-w to the child. Insert mode owns `Ctrl-w` = delete-word-back, so a tag being TYPED into swallows it; from a tag in normal mode it moves focus to the neighbour's BODY, as from a body, and from the top pane `Up` reaches the column and workspace tags | pardes-specific |
| `Alt-n` | new terminal below (outside raw tty) | shadows helix `Alt-n` (select next sibling), which pardes spells `Alt-right` alone | pardes-specific |
| `Alt-c` | move active terminal to a fresh column (outside raw tty) | helix `Alt-c` is change-noyank; the pardes window op wins (do-not-touch contract). `Alt-d` + `i` covers the behavior | waived (`alt-c-window-op`) |
diff --git a/docs/tags.md b/docs/tags.md
index b1d67f44..aa680c48 100644
--- a/docs/tags.md
+++ b/docs/tags.md
@@ -1,8 +1,9 @@
# Editable tags
Pardes has three levels of command text: the workspace tag, one tag per
-column, and each pane's tag. Column commands run in that column's active
-pane (or its first pane when focus comes from another column). This makes
+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.
`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.
@@ -164,7 +165,7 @@ upgrade to `Mode`; customized command text is preserved.
## Saved workspaces
`Dump` and `Restore` preserve customized workspace and column tags, including
-intentionally empty tags. New columns start with the standard column tag.
+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
@@ -175,7 +176,8 @@ 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.
-`ColumnTags` toggles the column row (on by default) without deleting its text.
+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.
@@ -183,3 +185,66 @@ 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. 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.
+
+`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).
+
+`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.
+
+One divergence from acme: acme keeps running when its last window closes,
+every column empty. Pardes quits when the session's last pane closes, as
+`Delcol` of the last column always has. A key, a prompt or a command in
+pardes runs in a pane, so a session without one would have nothing to run
+them in.
diff --git a/docs/themes.md b/docs/themes.md
index 8cc4ff9b..e028e806 100644
--- a/docs/themes.md
+++ b/docs/themes.md
@@ -108,12 +108,19 @@ so existing exported themes remain valid.
| `column_box` | Column grip while held, and its drag rail | `num` |
| `column_box_dim` | Column drag grip at rest, in every focus state | Equal mix of `column_box` and `tag_bg` |
| `border` | Quiet separators | `scroll_track` |
+| `empty_col` | A column with no pane, under its tag (acme: white) | `border` |
| `lineno_active` | Restrained current line number foreground | `lineno` |
| `search_bg`, `search_fg` | Search matches, independent of selection | `sel_bg`, `sel_fg` |
| `diagnostic_error` | Error text | `fg`, or `tag_fg` for an inherited foreground |
| `diagnostic_warning` | Warning text | Same foreground fallback |
| `diagnostic_info` | Informational diagnostic text | Same foreground fallback |
| `diagnostic_hint` | Hint text | Same foreground fallback |
+| `tag_sel_bg` | A tag's selection ground | `sel_bg` |
+| `sweep_bg`, `sweep_fg` | Three triples each: the select, exec and look sweeps' ground and ink | `sel_bg` tinted toward `kw`, `str` and `num`, in `sel_fg` |
+| `tag_rule` | The one-pixel rule between a pane's tag and its body, quieter than the `rule_px` rules between panes and columns | Halfway between `tag_bg` and the page the shell draws |
+| `rule_px` | Pixel shells: the width of the rules between columns, between panes stacked in a column, and under the workspace and column tags, in `border` (the rule between a tag and its body is always one pixel) | 2 |
+| `box_border`, `box_dirty` | The grip is acme's button: `box` filled when focused, else a two-pixel ring of `box_border` round the tag's ground; `box_dirty` fills it inside either ring while its file is unsaved (a grid, which has no ring, shows a bold `*` on `box_dirty` in the grip's second cell) | `box_dim`; `diagnostic_warning`, then `num` |
+| `rail_px` | Pixel shells: the scroll column's width, the grip's button over the scrollbar (thumb a pixel narrower), in pixels at a 17px tagline, scaled with it | 12, acme's Scrollwid |
Native palettes give filenames a distinct hue at approximately the same
brightness as the surrounding tag text. This also applies to output names
diff --git a/docs/ui-review.md b/docs/ui-review.md
index 58a42e61..1180a20e 100644
--- a/docs/ui-review.md
+++ b/docs/ui-review.md
@@ -98,8 +98,7 @@ tests and 797 SDL tests; SDL image/PDF and Kitty PDF rendering harnesses pass.
## Column and editable-tag follow-up
The follow-up adds editable workspace and column command rows, compact pane
-tags, staged buffer-name edits, caret reveal for long tags, and `ColumnTags`
-to reclaim the extra row when needed. See [editable tags](tags.md) for the
+tags, staged buffer-name edits, and caret reveal for long tags. See [editable tags](tags.md) for the
exact interaction and save-target rules.
`test/column_tags.py` exercises isolated SDL and TTY sessions against the same