diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/config.md | 30 | ||||
| -rw-r--r-- | docs/effects.md | 80 | ||||
| -rw-r--r-- | docs/fs.md | 130 | ||||
| -rw-r--r-- | docs/macos.md | 4 | ||||
| -rw-r--r-- | docs/selections.md | 27 | ||||
| -rw-r--r-- | docs/tags.md | 32 | ||||
| -rw-r--r-- | docs/themes.md | 6 |
7 files changed, 261 insertions, 48 deletions
diff --git a/docs/config.md b/docs/config.md index 6905446a..0332d854 100644 --- a/docs/config.md +++ b/docs/config.md @@ -322,8 +322,10 @@ name, thirteen required RGB roles (`sel_bg`, `sel_fg`, `tag_bg`, `tag_fg`, `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`, `empty_col`, `lineno_active`, `search_bg`, `search_fg`, -`diagnostic_error`, `diagnostic_warning`, `diagnostic_info`, and -`diagnostic_hint`. Missing new roles use backward-compatible defaults, so +`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 @@ -534,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`, @@ -614,7 +633,10 @@ writes a timestamped file in the default directory. A restored terminal comes back live: its recorded output (the last MiB of it) is replayed as history, a dim `── restored history ──` line marks where it -ends, and a new shell starts below it in the directory the old one was in. A +ends, and a new shell starts below it in the directory the old one was in, +the same shell it ran (a `Tty bash` pane comes back running bash). A view left scrolled back stays where it was. Only the shell is new; nothing the -old one was running is restarted. The web shell, which has no ptys, still +old one was running is restarted. A command pane comes back finished, with +what it printed and its `exit N`, and is not run again (a command still +running when dumped comes back as `exit ?`). The web shell, which has no ptys, still shows the history alone. 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. @@ -61,6 +61,8 @@ private namespace: 9ns --unix "$PARDES_9P" -- sh -c 'cat "$NINE_MOUNT/index"' ``` +(Under `9ns --unix`, `$NINE_MOUNT` is that session's root itself.) + A `9ns --unix` mount lives in the private namespace of the command it runs, and nothing outside that command sees it. The mount everyone on the machine shares is the registry one, `9ns --mntgen` (default `/mnt/9p`): every running @@ -127,7 +129,9 @@ Restore puts a new editor under every client, so the write of it is answered and then every connection is hung up, their fids naming the old editor's panes (a 9ns older than cloud9 2a7137c could fail the write with ECONNRESET all the same, when another request's send met the hang-up -before the answer was read; the log is the authority): dial again, and the new +before the answer was read; the log is the authority): dial again -- a 9ns +mount is one such connection, so after a Restore stop it and start 9ns +again, or every file under it fails -- and the new log names the restored panes and `restore <path>`. The answer has 200 ms to leave before the cut, so a slow client may see only the cut; the log's `restore <path>` is what says the @@ -137,16 +141,18 @@ never needed); and `Kill`, which does not quit but stops commands, as acme's does: bare, every command pardes started, and `Kill make ls`, those whose line begins with one of the words. A command pardes started is a command pane's, until its child exits -- Kill -sends its whole process group SIGTERM -- or a line it typed into a terminal (a +sends SIGTERM to its running job and to its shell, so the whole line stops +(of `sleep 30; echo done` the `echo` never runs) -- or a line it typed into +a terminal (a word written to `exec`, a middle click on one, a `pty/run`), from its shell's start mark (C) to its end mark (D), where Kill sends its foreground job SIGTERM -- acme posts the "kill" note, which ends a process -- and never signals the shell itself; in a shell running without job control (`set +m`) the job shares the shell's group, so there is none to signal: Kill says `Kill: no job to signal`, and a write of it to `ctl` fails with that; with nothing running -it says `Kill: nothing running`; and only the -foreground job, so of `sleep 30; echo done` the `echo` still runs once the -`sleep` is stopped -- +it says `Kill: nothing running`; and, of a typed line, only the +foreground job, so of `sleep 30; echo done` typed at a prompt the `echo` +still runs once the `sleep` is stopped -- and reads every setting there is, one a line, in the words a write of it takes (`Verbose on`, `WindowOpacity 70`, `PanelSlide off`, `DumpDir` bare for the default directory, `LocationsConfig ...`), so writing what it reads @@ -249,23 +255,32 @@ same tree without leaving the process. `src/builtins.zig` (`Save`, `Del`, `New`, `Newcol`, `Mount NAME DIAL`, `Unmount NAME`, `Dump`, `Restore`, `Msg TEXT`, `Find`, `Grep`, `Tty`, ...), or anything else, a command line. Written at a terminal at its prompt it - is typed into that shell. From anywhere else -- a file, a scratch, a tag, + is typed into that shell (and a terminal whose shell exits, `exit` typed + or run, closes its pane). From anywhere else -- a file, a scratch, a tag, a terminal whose tty a program holds -- it runs as a command pane: a terminal whose child is the root ctl's `Shell` (fish unless set) run - with `-c` and the line, in the pane's directory, + with `-c` and the line, in the pane's directory, with job control on + (bash, sh, dash, zsh, ksh `-m`; fish `status job-control full`), which shows its output and then `exit N` (its tag reads `<dir> (<line>) running`, then `exit N`), and stays. The command is over when its process exits, as in acme, not when its terminal closes: a job it left in the background prints on below `exit N` until it lets go of the pty, and a - command that lets go of its terminal early runs on to its own exit. The directory's next command runs in - that pane once it is done, below what it showed, after a `% <line>` line; + command that lets go of its terminal early runs on to its own exit. A + background job outlives the command: job control gives it a process + group of its own, so the hangup the kernel sends the terminal's + foreground group when the shell exits misses it. It survives the pane + closing too, but its writes to the terminal then fail, so start one that + must keep writing with `nohup` or its output redirected. The directory's + next command runs in that pane once it is done and nothing holds its pty, below what it showed, after a `% <line>` line; one still running gets a second pane. Before the next command the pane leaves any alternate screen and turns off the modes a program left on (mouse reports, bracketed paste, a hidden cursor); a command that clears the screen and its scrollback (`clear`, ED3) erases the history above it. A command pane's own exec starts the next command there too. The log says `run <serial> <line>` and `exit - <serial> <N|?>`; `exec` reads back the command pane's serial; Kill ends - its whole process group; a line is at most 1 KB. A misspelled word is a + <serial> <N|?>`; `exec` reads back the command pane's serial; Kill stops + its whole line; a line is at most 1 KB. To run a command again, execute + its line again from its directory: `echo 'make test' > pane/<n>/exec` on + the command pane runs it there, below the last run. A misspelled word is a command that says so and ends `exit 127`. `echo Tty > pane/<n>/ctl` makes an interactive terminal in that pane's directory. @@ -296,7 +311,9 @@ the tag is how to run `make` from that file), `Exec <text>` run by name the text, looked at or clicked (`# @`pytest -x`` in a script). A 9P `exec` is no gesture and is never sent: a script writes to the REPL pane's `pty/data`, multi-line code as a bracketed paste (`\e[200~<code>\e[201~` -then `\r`), since line by line a blank line ends a Python block and Python +then `\r`, and a second `\r` when its last line is indented: one Enter +leaves a block open, pasted or typed; a middle click sends that second one +itself), since line by line a blank line ends a Python block and Python 3.14's REPL auto-indents each line typed into it. The REPL gets the text wherever it is -- at a `pdb` or `input()` prompt too. Bindings are not dumped, so a Restore leaves none. @@ -312,12 +329,18 @@ not the hits buffer it opened. A look takes acme's addresses after a colon (editors/acme/look.c:450): a line written to `look` as `file:/re/`, `file:#n`, `file:$` or any address -opens (or finds) the file and selects what the address names, evaluated -from its dot; `:addr` does the same in the pane itself. `file:12` and -`file:12:5` stay line and column. A bare `/re/` is a path, as in acme, and -failing that a search for its text. A look that finds nothing, or an -address that does not evaluate, says so on the message row and changes -nothing: no buffer opens and the selection stays. +opens (or finds) the file and selects what the address names. **The +address is evaluated from the file's dot**, as acme's is: `file:/re/` +finds the next match after the current selection, not the first in the +file. For the first, start at the top: `file:0/re/` (or `file:#0/re/`). +`:addr` does the same in the pane itself, and a pattern may hold blanks +(`calc.py:/return a/`). `file:12` selects line 12, its newline included, +as acme's does; `file:12:5` puts the caret at line 12, column 5. A bare +`/re/` is a path, as in acme, and failing that a search for its text. A +look that finds nothing, an address that does not evaluate, or a line past +the file's end (`calc.py:99`) says so on the message row and in the log +(`err <serial> look: ...`), focuses and opens nothing, keeps the +selection, and leaves `look` reading back empty. `/pane/<n>/name` reads the pane's file name (a terminal's directory) and writing it renames the buffer; a relative name resolves against the pane's @@ -344,7 +367,13 @@ tab width — followed by rio's `current` or `notcurrent` (rio(4), `wctl`): whether the pane has the keyboard. It takes the pane's builtins (below), `get`, which reloads the buffer from the name it carries (unsaved edits are refused once, `<name>: Modified (get again to -discard)`, as acme's get asks winclean, exec.c:513), and acme's `lock` and `unlock` (editors/acme/xfid.c:603-611), for an +discard)`, as acme's get asks winclean, exec.c:513), `answer <choice>` +for the question the pane asks on its notice band, which the log names as +`ask <serial> <what> <choices>` -- `ask 4 del k j` for Del's side from the +keyboard (`k` the pane above takes the rows, `j` the one below), `ask 4 +repl a b` for which bound REPL takes an exec (a REPL's letter) -- `answer -` +taking it back as Esc does (with no question standing, `answer` is refused), +and acme's `lock` and `unlock` (editors/acme/xfid.c:603-611), for an edit of several writes to `addr` and `data` that another client must not land in the middle of. As in acme the lock binds only the clients that take it: a `lock` while another open holds it fails at once with `file in use` @@ -365,14 +394,19 @@ they also accept, so copying one onto another is all that acme's `addr=dot`, address expression (`#0,#5`, `/pattern/`, `2+1`, and pardes's own `12:5`, below); `addr` selects what `data` and `xdata` read or replace, `dot` is the editor's own selection and moving it -scrolls the pane into view, and `limit` bounds a search and reads empty until -it is set. Truncating `dot` empties it, truncating `limit` lifts it, and +scrolls the pane into view, and `limit` bounds only the end of a forward +search, as acme's does, and reads empty until it is set. Truncating `dot` empties it, truncating `limit` lifts it, and truncating `addr` leaves it as it is (below). A rename everywhere, or any other sam edit, is one write to the pane's `ctl`: `Edit ,x/foo/c/bar/` runs acme's Edit (docs/tags.md) on the body as one undo step; a failure fails the write with acme's words and changes -nothing. +nothing. A write is one message a line, except that an `Edit` line takes +the lines after it while its `{` group is open or its `a`, `c` or `i` text +block waits for its `.` line, on a pane's `ctl`, the root's (at the active +pane) and `exec` alike; an unclosed group is refused (``unmatched `{'``). +bash's builtin `printf` writes a line at a time, so write a block with a +heredoc or `env printf`. `line:col` is a pardes extension to sam's addresses, the spelling Look takes in `file:12:5`: `12:5` is the point at line 12, column 5, and it @@ -406,7 +440,15 @@ lazy `*?` included), searched the way sam searches (editors/acme/regx.c): as lines, so `^` and `$` match at the start and end of any line, `.` and a negated class never match a newline, and `$` also matches at the end of a text with no final newline. A pattern that names a newline (`\n`) runs over -the whole text instead, its `.` kept to one line. An expression is +the whole text instead, its `.` kept to one line; there a leading `^` still +matches at every line start, and `$` may stand just before a `\n` (where it +changes nothing). Any other `^` or `$` in such a pattern, `(^|\n)def` or +`a\nb$`, is refused with `in a pattern with \n, ^ can only come first and $ +only just before a \n`, since mvzr would read it as the start or end of the +whole text: never a search that silently finds nothing. Within a line, `^` +inside an alternation (`^def|^ `) matches only where the search starts, so it +works from a line's start (an `x` over lines, a `g` on one) and not from its +middle: an mvzr limit. An expression is evaluated from the current address, the range last written to `addr` (or left by the last `data` write, just past it), as acme evaluates it from `w->addr` (xfid.c:446): `.` is that address, not the selection (`dot` is @@ -448,13 +490,15 @@ The three flag files `dirty`, `mark` and `scroll` read `0` or `1` and take an undo point (writing `1` pushes one now), and whether a write scrolls the pane. -`tag` reads the whole tag as the pane shows it: the computed path, dirty -marker or PDF page, then the text you may edit. A write appends to that text, +`tag` reads the whole tag as the pane shows it: the computed path or PDF +page (no mark for unsaved text: the grip shows that, and `dirty` says it), +then the text you may edit. A write appends to that text, newlines included, and a tag with more than one line takes a row per line on screen; truncating `tag` clears it, as acme's `cleartag` does -- the default words (`Del`, `Put` and the rest) with it, since they are that text until you edit it, so `echo Make > tag` leaves only `Make`; append with `>>` to -keep them. The clearing is an edit of the tag like a typed one and its undo +keep them, with `printf ' Make' >> tag`: `echo` ends its word with a +newline, which starts a new line of the tag. The clearing is an edit of the tag like a typed one and its undo history is kept: `u` in the tag brings back the text it cleared, words included. @@ -472,9 +516,13 @@ an open renders its frame; stat the entry. `/log` is one ring (64 KiB) that records whether or not anyone reads it: `new`, `del`, `rename` (a terminal's too, as its shell changes directory, -since a terminal is named by its directory) and `save <serial> <name>`, +since a terminal is named by its directory), `exit <serial> <N>` before +the `del` of a terminal whose shell exited by itself, `ask <serial> <what> +<choices>` when a pane asks a question (answered by `answer` on its ctl), +and `save <serial> <name>`, `dump <path>` when a Dump is written and `restore <path>` in a Restore's -new log after its panes' `new`s, and `msg <serial|-> <text>` +new log after its panes' `new`s, then `restored <old> <new>` for each pane, +mapping the serial it had to the one it has now, and `msg <serial|-> <text>` for every line the editor says, repeats included (with `verbose` on, that includes each builtin announcing itself as it runs), and `err <serial|-> <file>: <why>` for every write or truncation the tree refused or that @@ -497,8 +545,11 @@ pane is being made can precede that pane's `new`; panes present at boot are recorded before anything else. Control characters in a record become spaces, so a record is one line. (An `event` record is not: acme's `<origin><action><q0> <q1> <flag> <n> -<text>\n`, whose text may hold newlines; read `n` bytes of it rather than -up to a newline -- bytes here, where acme counts runes. Every offset and +<text>\n`, whose text may hold newlines. The origin is `E` (a 9P write to body or tag), `F` (other +files, the editor's own lines), `K` (the keyboard) or `M` (the mouse); the +action's case says where: `x`/`l` a click executed or looked at in the tag, +`X`/`L` in the body, `I`/`D` text put in or taken out of the body, `i`/`d` +of the tag. Read `n` bytes of the text, not up to a newline -- bytes here, where acme counts runes. Every offset and count pardes serves is in bytes, `#n` and `q0`/`q1` too; the event count follows them rather than switch alone, so an acme library reads pardes correctly for ASCII text and not beyond it. A `#n` that falls inside a @@ -545,8 +596,14 @@ are read so that the answer costs the editor a bounded amount. `exit ?` is a command whose end mark carried no status, which is not a success; `error out of memory` is an answer that could not be made. The header is always the whole first line. It reads -`busy` at once when a command is running or text is typed at the prompt, -which is also when the third field of `pty/status` reads 1. A line written +`busy` at once when a command is running or text is typed at the prompt +-- a run is a line typed at the shell's prompt, so a program holding the +terminal (a REPL, `less`) takes none: write to `pty/data` for it -- +which is also when the third field of `pty/status` reads 1. `pty/status` is +one line, three right-aligned fields and a newline: the pty's columns and +rows, then busy (0 or 1). The size, and `pty/ctl`'s `winsize` read back, is +what `winsize C R` last set, until the pane itself resizes and gives the pty +its grid again. A line written before a new terminal's shell has drawn its first prompt is not busy: it waits for that prompt (a respawn meanwhile keeps it waiting for the new shell's) and is sent then, so the first command a script gives a fresh @@ -555,8 +612,13 @@ could not instrument, or a startup that hangs) leaves such a line waiting for ever: cancel the read (interrupt it, or close the open) to give up; `error not run` when the shell refused the line without running it (a fish syntax error; the line is taken back off -the prompt); `error shell gone` when the pane closed or its shell was -replaced; `error no prompt marks` for a shell pardes could not instrument; +the prompt): the shell's marks say only that it did not run, so the answer +carries no reason or code, and the shell's own complaint is in the pane's +body (`tail body`); `exit N` and what it printed when the line ended the shell +itself (`exit 3`, or `echo bye; exit 3`): its terminal closes, and a read +of the run's open still answers after the pane is gone; `error shell gone` +when the pane closed or its shell was replaced, or the shell went without +an exit status to tell; `error no prompt marks` for a shell pardes could not instrument; `error command done; not a shell` (or `error a command runs here, not a shell`) on a command pane, whose child is its command. It relies on the OSC 133 marks pardes injects into bash and fish, tagged diff --git a/docs/macos.md b/docs/macos.md index 5166e2d5..cf7091e6 100644 --- a/docs/macos.md +++ b/docs/macos.md @@ -355,8 +355,8 @@ The dirty half needed one core watermark. `File` counted `revision` but never recorded which edit was last *written*, so no shell could derive "unsaved" — `File.saved_revision` is that watermark, advanced by `Save` at the moment the write is asked for and by a successful external-file reload whose bytes -already came from disk. The core renders the same answer as ` *` after the -path in every tagline, while this host also puts it in the native close button. +already came from disk. The core shows the same answer on each pane's grip +button, while this host also puts it in the native close button. Save is marked at ask-time rather than on completion because `save_file` carries none back, which makes both indicators exactly as honest as the Save request. diff --git a/docs/selections.md b/docs/selections.md index 5cc1df1a..0817c215 100644 --- a/docs/selections.md +++ b/docs/selections.md @@ -121,3 +121,30 @@ the replay. line is its own haystack, so `^`/`$` hold at every line and a class like `\s` does not reach the newline unless the pattern names `\n`. - Undo restores only the primary (above). + +## The mouse + +A B1, B2 or B3 sweep selects a stream, as acme's does (libframe +frselect.c:115): from the press to the end of its line, the lines between +whole, the last from its start to the release, the character under the +pointer included. A plain B1 click puts the caret on its cell. A second +plain click at the same cell within half a second is acme's double-click +(plan9port acme text.c:1407, textdoubleclick): just after `{ [ ( < «` or +just before their closers it selects up to the match, nested pairs +counted; at a line's start or end the whole line; just inside `' " \`` +the quoted text; anywhere else the word (letters, digits, `_` and any +non-ASCII character). It works in bodies, tags and a terminal in normal +mode; a terminal whose program has the tty gets its own clicks. + +A B2 or B3 pressed while B1 holds a sweep is acme's chord: B1-B2 cuts, +B1-B3 pastes over it. Everything done while B1 stays down is one undo +step, as acme marks the file once per B1 hold (text.c:881, textselect), so +B1-B2 then B1-B3 is a copy: the text cut and pasted back, the cut text +left in the register. + +A B1 sweep held past a pane's top (on its tag) or bottom (past it, or on +its last row when the pane reaches the screen's bottom, which the pointer +cannot leave) scrolls the body a line a tick, as acme's frselect scrolls, +the sweep's end under the pointer and its start on its text. A sweep that +scrolled ends as the text's own selection, from where it began to where it +ended. B2 and B3 sweeps do not scroll. diff --git a/docs/tags.md b/docs/tags.md index b8299f22..aa680c48 100644 --- a/docs/tags.md +++ b/docs/tags.md @@ -72,21 +72,33 @@ 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, and may hold more than one line. A tag with a newline in it takes -a row per line, up to eight: a pane's tag leaves its body at least one row -and a collapsed pane shows only the first line; the column and workspace -tags take no more than a third of the screen, and the panes below move down -to make room. The path, the dirty marker and a PDF's page at the start of a +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 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, the dirty marker, a PDF's page) the cursor keeps +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; -tags reveal the caret horizontally when text is wider than their column. +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 @@ -170,6 +182,10 @@ ignored, with a message saying so. 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. 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 diff --git a/docs/themes.md b/docs/themes.md index 103a3f5a..e028e806 100644 --- a/docs/themes.md +++ b/docs/themes.md @@ -115,6 +115,12 @@ so existing exported themes remain valid. | `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 |
