summaryrefslogtreecommitdiff
path: root/docs
Commit message (Collapse)AuthorAge
* A focus write makes its pane's column the active one, and layout's active is itGabriel Schneider3 days
| | | | | | | | | | | Writing a serial to /focus gave that pane the keyboard but left the active column where it was, so pane/new under Placement acme went elsewhere, and /layout's active named the keyboard's column rather than where a new pane would go. A focus write now sets the active column as the user's click there would, under either Placement, and /layout's active names the active column, which pane/new and a look place into. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A desktop session holds 64 panes, and every route that finds none free says soGabriel Schneider3 days
| | | | | | | | | | | | | Sixteen panes was far too few for a real session. MAX_PANES is now 64 on a desktop and stays 16 on the board; the 48 more slots cost about 3.7 KB each in fixed tables (the core 1.33 to 1.45 MB, its surface 19 to 72 KB), and a pane itself (84 KB and its terminal) is allocated only when it opens. At the cap, pane/new fails with `pane/new: no pane slots: 64 max` and an err record rather than a bare ENFILE, a 9P look or exec that would open a pane fails its write with the same words and reads back empty, and New, Tty, Tutor and Alt-n say it on the message row (their ctl writes fail with it). Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A repeat inside a regexp group gives back to what follows the groupGabriel Schneider3 days
| | | | | | | | | | | | | | On aab, /a+ab/ matched but /(a+)ab/ and /(a*)ab/ missed, and so did (.+)_area and ([a-z_]+)_area, in addr, Edit and look alike. mvzr's hasAlt counts a group's own ) as an alternative, so every group with pattern after it takes matchGroup's alternatives branch, which never tries a repeat's shorter matches. No newer mvzr fixes it (trunk is the pinned commit), so the build patches the fetched source as it does the step budget, anchor-checked: when the rest fails after a group, the group's shorter matches are tried, longest first. docs/mvzr-group-backtrack.md is a report for upstream. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Columns are named by stable serials over 9P, as panes areGabriel Schneider3 days
| | | | | | | | | | | /col/<n> named a column by its index, which shifts when a column left of it closes: exactly what scripts trip on. A column is now /col/<serial>, its serial kept while it lives and never reused; /layout lines give serial and index (`<serial> <index> ...`), active names the serial, /index's last field is the column's serial, and the log says newcol and delcol with serials. Docs, the skill and the tree's README say so. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A pane's last row of text is no resize handle; the grip is, and the GUI's ruleGabriel Schneider3 days
| | | | | | | | | | | | | | | A press on a pane's last row began a seam drag, so the row could not be clicked or swept like the rest of the text (rsearch dragged the handle out of the way first). Now no row of text is a handle: in the GUI a press on the 2 px rule between two panes drags their seam, and anywhere the grip does, as acme's button moves a window -- dragged up or down its own column it moves the pane's top, either pane down to its tag alone (acme's coldragwin), dragged down inside itself too. The hover hint over a last row is gone; column edges resize as they did. Scripts that dragged a seam drag a grip instead and match their goldens; six goldens lost the hint or moved a cursor to the clicked text, re-recorded by name. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* The tree serves the layout: /layout, /tag and /col/<n>/tagGabriel Schneider3 days
| | | | | | | | | | | | | A script could not see where the panes sit or edit the tags a person clicks in. /layout lists each column, its index, x and width in cells, current or not, empty or full, and its panes' serials, then the active column; /tag is the workspace tag and /col/<n>/tag a column's, read and written as a pane tag is (one line: a newline written in is a space, and a truncating write drops the one ending it); /index's lines end with the pane's column; the log says newcol <n> and delcol <n>. acme serves no column files, and the docs say so. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Docs answer round 7's questionsGabriel Schneider3 days
| | | | | | | | | The grip's two terminal cells (the mode, then * for unsaved text), a new terminal's new N / then rename and the ls it runs at its first prompt, the tag offsets an x record carries, Del k and Del j, each builtin's msg in the log and its serial, and m=$NINE_MOUNT under 9ns --unix in the skill. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A dump keeps the settings changed from a fresh session's, and Restore sets themGabriel Schneider3 days
| | | | | | | | | | | A session running with Placement pardes came back from Restore as acme: a dump kept the layout and the theme but no setting. It now keeps every setting line that differs from a fresh session's, as the root ctl reads it, and a Restore applies them; the theme stays where it was kept, the font the frontend's, and REPL bindings are still dropped. The dump golden gains the three the snapshot harness sets. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A GUI-only setting says so on a terminal, and DumpDir reads back its directoryGabriel Schneider3 days
| | | | | | | | | | `Lift on` over ctl on a terminal answered "unknown control message" while Config listed Lift as unsupported, and the ctl's DumpDir line read bare while Config showed the path in effect. A setting word this frontend lacks is now refused as `Lift is GUI-only` (GripWidth too), and DumpDir reads back the directory in effect, as Config does. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A send to Python's REPL runs once, the Enter after the paste, not in itGabriel Schneider3 days
| | | | | | | | | | | | A one-line send (print(1)) to Python 3.14 stopped at ... and needed another Enter: its REPL takes a bracketed paste, and an Enter read in the same read as the paste is part of the paste, one line or not (checked in a real pty). Into a REPL that asked for bracketed paste, the Enters (two for an open block) now wait for its next output, its answer to the paste, or 250 ms with nothing. fs-test runs python3 in a real pty and checks a one-line exec prints at once; the docs' pty/data recipe says to send the Enter apart. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A truncating write to tag drops the one newline that ends itGabriel Schneider3 days
| | | | | | | | | `echo X > tag` stored X and a trailing newline, which drew an empty tag row. After a truncation the newline ending each write is held back until more text follows or the open is released, so the one ending the whole of it is dropped and any other stays; `>>` keeps what it is given. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Del and Delcol refuse unsaved text once, as acme's doGabriel Schneider3 days
| | | | | | | | | | | | acme's Del asks winclean first and Delcol colclean (exec.c del, delcol): unsaved text is warned about, and the same word again closes. pardes closed at once. Both now refuse once through the one-warning-per-word mechanism Exit uses, from keys, tags, exec and ctl alike. A pane dirty only by a rename, or an empty one that never held a file, has no text to lose and is not asked about, and a scratch or a command's output under 100 bytes is not either, as acme's winclean passes a small unnamed window. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* Exit and Restore name a modified +New scratch too, in one wordingGabriel Schneider3 days
| | | | | | | | | | Their refusal named only file panes, so text typed into a +New scratch went unasked about and was lost. A scratch with text counts as unsaved as a file does (acme's winclean asks about an unnamed window too). The refusal a ctl write gets now reads as the message row does, `<names>: Modified (Exit again to discard)`, instead of a second "discard them all" wording. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A choice setting's refusal names what it takes, and /commands lists themGabriel Schneider3 days
| | | | | | | | | | | | Bare Placement and BootShell flip, which is pardes's convention for a word that chooses (Crt does too), but nothing said so, and "bad value in control message" never said what would do. A refused value now says `takes acme, pardes` (every switch and choice setting), /commands lists each such setting's values in a fourth field, and config.md and fs.md say that bare steps to the next. Motion and ShaderAnimation stepped nowhere bare and now step like the rest. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* An answer the question does not offer is refused, and the question standsGabriel Schneider3 days
| | | | | | | | | `answer z` to a question offering a and b succeeded, sent nothing and dropped the question; so did Del's `answer x`. The ctl now takes only an offered choice or -, refuses anything else with the choices it takes (`answer takes k j or -`), and leaves the question asked. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* A tag that exactly fills its row stays one row, as acme's doesGabriel Schneider3 days
| | | | | | | | | | | | | | | Tags wrapped one cell early to keep a cell for the caret past a full row, so a tag that exactly filled its column broke as De / l. acme's frame wraps a box only when it is wider than what the row has left, and frptofchar clamps the tick past a full line's end to the frame's edge. Tags now wrap at their full width; the caret past a full row sits at the tag layer's edge, and on the pane's last cell in a terminal grid, which has none past it. Two tiny-screen tests collapse their tags, as the others do, and the 41 goldens that moved were re-recorded by name after the same check: rows shift back up under the shorter tags and nothing else changes. chordcut's file-body clicks moved back with them. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* design.typ no longer says ColumnTags hides the column tagGabriel Schneider3 days
| | | | | | | | | The empty-columns line removed the ColumnTags setting: a column's tag is always shown. design.typ was the one document still describing it; ui-review.md and test/column_tags.py never named the setting and already assume the tag is there. Co-Authored-By: Claude Opus 5.5 <[email protected]>
*-. Merge: 9P round 6 + empty columns + render (acme theme, grips, Lift, Motion)Gabriel Schneider3 days
|\ \
| | * Motion flavours differ by design, and drive notice drops and pane movesGabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The flavours looked alike because Lift, the only motion that read them, moves a shadow a few pixels: overshoot and wind-up were sub-pixel. By design now: crisp leaves at full speed and never passes its mark; smooth (the default) eases in and out in twice crisp's time, a slide arriving in 208 ms (inside §8.1's 220); bouncy passes its mark by ~30% and settles twice; playful winds up, passes by ~40%, and stretches and squashes, text included (the user's choice). Small motions are exaggerated by the flavour's gain. Motion gains launch, gain, span and norm, and ease(u)/speed(u) for moves of fixed length. The notice drop follows ease() over its fall (alpha never behind its position) and stays inside its pane's body past its row. Panel tracks carry the flavour in Track.motion (the old padding byte; macOS header name follows); opening and moving slides, zooms and rises follow it over span x their frames; landed, a pane is exactly its target; closing keeps its own exit. A pane past its mark never takes a neighbour's click; a rising one stays in its box. Tests: each flavour's lift trajectory distinct; flavour character; exact landing bit for bit; a stretched pane's drawn cells map back; the overshoot hit rule; the vertical clip at peak; legacy tests pinned to crisp. GUI golden 18-mid-transition changes (the retuned smooth slide at frame 6). Shared files: src/animation.zig, src/Presentation.zig, src/Messages.zig, src/macos.zig, src/config.zig, src/pardes.zig tests, src/ninep/screen.zig test, docs/effects.md, docs/config.md.
| | * acme looks like acme; every theme gets acme's button, scroll column and 2px ↵Gabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | rules acme takes plan9port's own colours (acme.c iconinit, draw.h): selections #eeee9e in the body and #9eeeee in the tag, black ink; exec and look sweeps #aa0000 and #006600, white ink; a #99994c scrollbar under a #ffffea thumb; black rules; a #8888cc tag/body rule and column button. Every theme: the grip is acme's button, its tag row's full height, in one scroll column with the scrollbar (rail_px, 12 at a 17px tagline, scaled, times GripWidth, a percent, default 150; same x0/x1 to the pixel): focused clean = solid box; focused dirty = box_dirty filled to a box ring (acme's modbutton); unfocused clean = a box_border ring round the tag's ground; unfocused dirty = box_dirty a pixel inside that ring. The grid, which has no ring, marks dirty with a bold * on box_dirty in the grip's second cell and fills an unfocused grip halfway to its ring. Regions carry a dirty flag. Column buttons are the same shape, solid. 2px rules between columns and stacked panes (inside the tag band's slack), none at the window edge; a 1px tag/body rule halfway between tag and page. Theme data: tag_sel_bg, sweep_bg/fg, tag_rule, rule_px, rail_px, box_border, box_dirty. Chrome: rule_px, tag_rule, rail_px, grip_border, grip_focus_ring; a comptime guard on Chrome's layout forces a wire bump once v8 ships. Structural rules are exempt from the focus-indicator rule (docs/effects.md). Tests: acme widths; stacked rule in the slack at two tagline sizes; every grip-column pixel is band, button, ring or rule, and the button shares the scrollbar's x0/x1 (4 metrics x top/bottom x focus x dirty); the four grip states distinct in every native theme with a non-colour dirty cue in the grid; wire round-trip of the new fields. Shared files: src/colors.zig, src/surface.zig, src/body_layer.zig, src/tagline.zig, src/detached/wire.zig, docs/themes.md, docs/config.md, docs/effects.md, 21 snapshot goldens (the grip cells only), test/gui-goldens.txt. Motion flavours differ by design, and drive notice drops and pane moves
| | * Motion flavours, and Lift is shadow, rim or auto: auto on a dark page ↵Gabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | recedes the other panes (InactiveDim) Motion off|crisp|smooth|bouncy|playful is one parameter set (animation.Motion) every fx animation reads. One focus spring per pane drives both the lift and the dim, at the flavour's pace; a grid snaps. Lift drops glow and surface. A shadow falls on pane bodies and rails only, capped so text and the selection keep min(contrast, 4.5); rim is a hairline along the focused tag's top. auto is a shadow on a light page; on a dark page the core recedes the unfocused panes' text (InactiveDim, ported from 2e4d97f, default 30 under auto) with the same floor. Tests: focused text contrast is never below unfocused in any style, dim or theme; the focused pane's cells and tag are untouched by a dim. Shared files: src/config.zig, src/builtins.zig, src/ninep/ctl.zig, src/surface.zig, src/detached/wire.zig, docs/config.md, test/snapshots/builtins.snap (one more wheel for the longer help).
| | * G1: Lift, soft elevation shadows (off by default)Gabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | `Lift` (a GUI toggle, capability lift) lifts the focused pane on a critically damped spring (animation.Spring: closed form, about 240 ms to settle, velocity kept across retargets, settled = no frames) and floats notices. The core puts the lift on the regions (Region.lift, on the wire); the GUI casts from it: a soft shadow is decor, an erf rectangle on one quad grown by 3 sigma (decor.frag, flag 0x10000000), in the quad's own space so a track's transform carries it; darken-only, the caster's rect left alone, alpha pre-warped for linear light and IGN-dithered. Cast last in its group, so a neighbour's rails and rules darken with its text; a notice's before its rule. Strength is capped per theme so text over the darkest shadow keeps min(its contrast, 4.5) (test over the native themes). Opt-in until the focus lift/dim default is decided. Feel review material: docs/effects.md. Test-mode PARDES_TEST_SERIES keeps every captured frame. Shared files touched: pardes.zig (two fields, one nextWake line), detached/wire.zig (lift on the region), config.zig, builtins.zig (capability), gui.zig. Not touched: Messages.zig, mouse.zig, tty, host_io.
| * | A document dragged beside the boot shell leaves it; BootShell replace closes ↵Gabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | it as before Placement and BootShell are one kind of setting now, a word from an enum, set, flipped bare, and reported by one arm. Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * | An empty column shows its theme's empty_col: white in the acme theme, as ↵Gabriel Schneider3 days
| | | | | | | | | | | | | | | | | | acme paints it Co-Authored-By: Claude Opus 5.5 <[email protected]>
| * | A column can be empty, as acme's can; new panes go where acme's ↵Gabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | makenewwindow puts them Newcol makes an empty column; closing a column's last pane leaves it empty with the keyboard on its tag; Delcol and Joincol alone take a column away; the session's last pane closing quits. The +New stand-in and replaceStillborn / stillborn_joiner are gone. Every new pane goes through exec.placeNew, which follows acme's makenewwindow (active column, empty column whole, blank space, halving the biggest) or, with Placement pardes, the old rules. ColumnTags is gone: column tags are always shown. A grip drag shows acme's box cursor. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | fs.md answers round 6's doc questionsGabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | Event origins and the case of an action (tag x, body X), printf rather than echo for >> tag, pty/run only at a shell prompt, why error not run gives no reason, how to rerun a command pane, a shell's exit closing its pane, Kill stopping a command pane's whole line, and restarting 9ns after a Restore. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | Kill stops a command pane's whole line again, now it runs with job controlGabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | With the line run under job control (the change before), the job running has a group of its own, and Kill's SIGTERM to the tty's foreground group stopped only that job: of `sleep 30; touch x` the touch still ran. For a command pane the hosts now signal the shell's group as well, so the whole line stops, as it did; a line typed at a prompt still loses only its foreground job. The test forks a real pty for both halves: a background job outliving its command and the pty's hangup, and a killed line not running on. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A Restore logs restored <old> <new> for each paneGabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | A script holding serials from before a Restore could not find its panes: the replacement numbers them afresh. The dump now keeps each pane's serial (0 in older dumps), and the replacement's log says `restored <old> <new>` for each after its `restore <path>`. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A restored command pane comes back finished, not as a live shellGabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | After Restore a dogfood agent's command panes were fish shells under a stale `(make) exit 0` tag. The dump's terminal record now keeps a command pane's line and status, and Restore brings it back done: what it printed, its exit, no shell and no rerun. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A pane's question is logged as ask, and answer on its ctl answers itGabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A script could not answer the several-REPLs question, which only a key could. Every question a pane asks on its notice band (which REPL takes an exec, Del's side from the keyboard) is now logged as `ask <serial> <what> <choices>`, and `answer <choice>` on the pane's ctl answers it as that key would, `answer -` taking it back as Esc does. One function answers for a key and for the ctl. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A Python block sent to a REPL gets the second Enter that ends itGabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A dogfood agent's `def` sent to python3 sat open at the continuation prompt: a block whose last line is indented is not over at one Enter, pasted into 3.13's REPL or typed into the old one (checked against python 3.14 in a real pty, both ways). A send to a Python REPL now adds that second Enter, and the pty/data recipe in the docs and the 9P skill says to. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | Restore brings a Tty bash pane back running bashGabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | A dogfood agent's `Tty bash` pane came back from Restore running fish: the dump kept its directory but not the shell it was opened on. The dump's terminal record now carries that shell (empty for the configured one, as older dumps read), and Restore starts it again. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A command pane's background job outlives its commandGabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A dogfood agent's background jobs died when the command that started them finished, even under nohup. The command's shell leads its terminal's session, and on its exit the kernel hangs up the terminal's foreground group, which with job control off is the shell's and every job's. The line now runs with job control on (bash, sh, dash, zsh, ksh -m; fish status job-control full), so a job has a group of its own and lives on, printing below exit N, and survives the pane closing. While a job holds the pty the pane is not reused, so the directory's next command gets a second pane (cmdexit's golden, re-recorded by name). Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A shell that exits under a run answers exit N, and the log says exit before delGabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A dogfood agent ran `exit 3` through pty/run: the reader got ENOENT, and the log went straight to del. The hosts now read a shell's exit status at its pty's end as they do a command's; a run waiting on the line answers `exit 3` with what it printed, the log says `exit <serial> 3` before the pane's `del`, and an open run still stats after its pane is gone (cat fstats its input). Pins cloud9 f35b7ed, whose stat of an open fid names its open. Writes to a gone pane's pty/data, held open or not, fail ENOENT. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | pty/status reads the pty's size as winsize set it, on a line of its ownGabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | A dogfood agent wrote winsize 100 30 to pty/ctl and pty/status went on reporting the pane's grid, and the status line had no newline to end it. The size winsize sets is kept until the pane resizes and gives the pty its grid again; ctl's winsize read back and status both report it, and status ends with a newline. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A pane tag wraps onto rows and can collapse to one, as acme's doesGabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | acme's frame wraps a tag at its right edge and the window grows to show every row (wind.c wintaglines); Tagup/Tagdown shrink it to one row and back. Pane tags used to be one row, scrolled sideways to the caret. Now a tag's lines wrap at its width (one cell kept for the caret past a full row) and it starts expanded; insert-mode Up on the first row collapses it, Down on the last row expands it, and Alt-Up/Alt-Down do so in either mode. A word the wrap breaks across rows is still one word to a click and a selection. Column and workspace tags keep scrolling sideways. Tests read body rows relative to the body's first row; the 41 snapshot goldens that moved were re-recorded by name after a programmatic check that each differs only by body rows shifting under the taller tags, and twelve scripts whose clicks targeted fixed rows now click the same text. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A look with a blank in its pattern addresses, file:N selects the line, and a ↵Gabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | miss is said, logged and reads back empty Round 6: look calc.py:/return a/ was a word search, since a blank ended the address; calc.py:99 past the end focused the file and said nothing; and /look still read back the pane before a miss. A pattern after the colon may now hold blanks; file:N selects the line, newline included, as acme's does; a line past the end opens and focuses nothing; and every miss (no match, a bad address, a line past the end) says so, logs err <serial> look: why, keeps the selection, and leaves look reading back empty. Documented, with file:0/re/ for the first match, since acme evaluates the address from the file's dot. Five goldens change: a look at file:N now selects the line. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A tag no longer marks an unsaved file with *: the grip shows itGabriel Schneider3 days
| | | | | | | | | | | | | | | | | | The grip button now shows a pane's unsaved text in every state, as acme's modbutton does, and acme's tag has no asterisk. The computed prefix is the name alone, so tag reads, event offsets that count the path and the tag's text lose the " *". dirty, index's flag and the refuse-once guards are unchanged; a dump from before still restores its tags past the old mark. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A B1 sweep held past a pane's edge scrolls the body, as acme's frselect doesGabriel Schneider3 days
| | | | | | | | | | | | | | | | | | Dragging a selection beyond the top or bottom of a pane stopped at the last visible row. Now, while B1 is held past the body's top or bottom (at a pane that reaches the screen's bottom, its last row, since the pointer cannot leave the screen), the body scrolls a line a tick; the sweep's start keeps its place in the text, and a sweep that scrolled ends as the text's own selection. Also here: a ctrl-click is not half a double-click (lspdebug's golden stays as it was), and a test that clicks many points in a row resets the double-click between them. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | Everything a B1 chord does while B1 is down is one undo stepGabriel Schneider3 days
| | | | | | | | | | | | | | | | | | B1-B2 then B1-B3 cut and pasted as two undo steps. acme marks the file once per B1 hold (text.c:881, textselect), so the pair is a copy. The chord now takes one undo point when it begins and its edits share it until B1 comes up. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A double-click selects as acme's does: a word, a line, a bracketed or quoted ↵Gabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | text A second B1 click at the same cell selected nothing more. Now, as acme's textdoubleclick (plan9port text.c:1407), it selects up to the match of a bracket just before or after the point, the whole line at a line's start or end, the quoted text inside ' " `, or else the word, in bodies, tags and terminals in normal mode. A plain click still puts the caret on its cell. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | Column and workspace tags are one line again, as acme'sGabriel Schneider3 days
| | | | | | | | | | | | | | | | | | acme gives a column tag one font height (cols.c:244) and its row tag one line; pardes let them grow a row per line. A newline typed, pasted, written or restored into a column or workspace tag now becomes a space, the caret and selection kept on the same characters, and the bars are one row each. A dump holding a multi-line header tag comes back with its lines joined by spaces. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | A write of an Edit block reaches Edit whole, on a pane's ctl, the root's and ↵Gabriel Schneider3 days
| | | | | | | | | | | | | | | | | | | | | | | | exec Every write was split into lines, so a { group or an a/c/i text block written to ctl or exec became lines of their own: i/.../ and } ran as shell command panes that exited 127. An Edit line now takes the lines after it while its group is open or its text block waits for its . line (sam_edit.needsMore, asking sam's parser), on all three; the root ctl takes Edit at the active pane. s/re/text/N counts as sN/re/text/ does. The docs and the skill show a block written by heredoc or env printf, since bash's printf writes line by line, and take round 5's doc list: get refusing once, the (xN) on a repeated err, limit bounding only a forward search's end, line:col's clamping, and $NINE_MOUNT under 9ns --unix. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | | ^ in a pattern with \n matches at every line start, and a ^ or $ that cannot ↵Gabriel Schneider3 days
|/ / | | | | | | | | | | | | | | work is refused A pattern naming a newline runs over the whole text, where mvzr's ^ is only the text's start: /^def .*\n/ from #0 failed, and Edit ,x/^def .*\n/.../ silently did nothing. A leading ^ is now tried at each line start from the search's own; $ just before \n is dropped, as it changes nothing; any other ^ or $ in such a pattern is refused with why, since mvzr would read it as the text's ends. ^ inside an alternation holds only where a search starts, an mvzr limit, documented. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | Edit runs sam's command language on a pane's body, as acme's Edit does, in ↵Gabriel Schneider3 days
| | | | | | | | | | | | | | | | one undo step Over 9P a rename everywhere was a loop of addr and data writes. Edit, from a tag, a pane ctl or exec, parses sam's commands as acme's edit.c does and runs them as ecmd.c does against the text as it was, collecting the changes in order as elog.c logs them and applying them at once: addresses (the addr file's, line:col included), x y g v c a i d s p = m t, u alone, and { }. One undo step; any error, in acme's words, changes nothing, fails a ctl write and is logged. p and = print to the directory's +Errors. Left out, and said: the file commands, the pipes, \1-\9 (mvzr keeps no submatches), and changes out of sequence, which acme applies with a warning. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | addr takes line:col, as Look's file:12:5 doesGabriel Schneider3 days
| | | | | | | | | | | | A script that knows a line and column had to count bytes to write #n. `12:5` is now the point at line 12, column 5 (bytes from 1, clamped to the line's end and snapped to a character's start, as Look's cursor is), and it composes like any simple address. A pardes extension, documented as one; sam reads it as a syntax error. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | The docs say how a --detach=NAME session is posted, what > does to tag, ↵Gabriel Schneider3 days
| | | | | | | | | | | | | | | | where #n inside a character lands, and what tag click offsets count; a refusal says which ctl takes the word, and a lock refusal who holds it Dogfood round 4's doc list: the recipe assumed pardes/<pid>; the README said tag writes append, though > replaces the editable text; #n inside a multibyte rune or grapheme snaps to its start, unsaid; a tag click's offsets count the path. A word written to the other ctl now says write it to pane/<n>/ctl or /ctl, and a held lock says another open of that ctl holds it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A followed log, event or pty/data answers a read inside its last answer from ↵Gabriel Schneider3 days
| | | | | | | | | | | | | | | | it again, so bash's read loses nothing bash's read on a seekable fd takes a chunk, keeps one line and lseeks back to just past it; a stream had already moved on, so the rest of the chunk was lost and a while-read loop over the log dropped records. Each stream open keeps its last answer and the offset it was read at, and a read strictly inside it is answered from it; a read at the same offset, as a client that ignores offsets makes, still gets the next record. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | A shell's > on addr no longer resets it, so echo /re/ > addr searches onGabriel Schneider3 days
| | | | | | | | | | | | Truncating addr reset it to #0, so a shell's find-and-replace loop matched the first hit for ever, .+#1 read 1 1 each time, and foo x foo y foo became foobarbarbar... acme resets addr on the first open (xfid.c:105-108), for clients that hold the fid; a shell cannot. Here neither an open nor a truncation resets it: the address written is evaluated from the last one, and 0 or , starts over. Documented as a departure from acme. Co-Authored-By: Claude Opus 5.5 <[email protected]>
* | get on a pane with unsaved edits refuses once, as acme's doesGabriel Schneider3 days
| | | | | | | | | | | | A ctl get threw unsaved text away at once. acme's get asks winclean first (exec.c:513): warned once, the same get again discards. A pane dirty only because it was renamed has no text to lose, and is not asked about. Co-Authored-By: Claude Opus 5.5 <[email protected]>