diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/config.md | 38 | ||||
| -rw-r--r-- | docs/effects.md | 80 | ||||
| -rw-r--r-- | docs/fs.md | 9 | ||||
| -rw-r--r-- | docs/helix-keys.md | 2 | ||||
| -rw-r--r-- | docs/tags.md | 73 | ||||
| -rw-r--r-- | docs/themes.md | 7 | ||||
| -rw-r--r-- | docs/ui-review.md | 3 |
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. @@ -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 |
