diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-29 03:14:45 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:15 -0300 |
| commit | 7fe3a1d9a9ee3c2510ecac40e079608447eead70 (patch) | |
| tree | 01cf469853198f2def268745254253a786c34718 | |
| parent | a7960117dfb83ad65a0466a96affbbb524936b7f (diff) | |
| download | pardes-7fe3a1d9a9ee3c2510ecac40e079608447eead70.tar.gz pardes-7fe3a1d9a9ee3c2510ecac40e079608447eead70.zip | |
The docs give the full-column refusal, an Edit block left open at close, and byte columns
Round 11's doc findings: the skill names the full-column refusal beside the
64-pane cap; fs.md and the skill say an Edit block still open when its open
closes fails with unmatched { and an err; and line:col's byte columns get
the tip for character columns from tools (the same on ASCII, else a
search or #n). A unit test pins the unmatched { at close.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
| -rw-r--r-- | .agents/skills/pardes-9p/SKILL.md | 6 | ||||
| -rw-r--r-- | docs/fs.md | 11 | ||||
| -rw-r--r-- | src/ninep/tree.zig | 11 |
3 files changed, 23 insertions, 5 deletions
diff --git a/.agents/skills/pardes-9p/SKILL.md b/.agents/skills/pardes-9p/SKILL.md index 38f84e77..e64c0118 100644 --- a/.agents/skills/pardes-9p/SKILL.md +++ b/.agents/skills/pardes-9p/SKILL.md @@ -95,7 +95,8 @@ $m/pane/new open it to make a pane (a scratch named <dir>/+New), read names it the ACTIVE column (the one last typed or clicked in, or Newcol's), filling it if empty, else taking the bottom half of its last pane (ctl `Placement pardes`: the old rules); a session holds 64 panes (16 on the board): past that, every route that opens one - fails with `no space for a pane: 64 max` (ENOSPC); rmdir $m/pane/<n> closes it; a column's last pane leaves the column EMPTY + fails with `no space for a pane: 64 max` (ENOSPC), and so does one whose column + has no rows left (each pane keeps its tag and 2 rows: `no space for a pane in that column`); rmdir $m/pane/<n> closes it; a column's last pane leaves the column EMPTY (focus reads empty, the log says only del), and the session's LAST pane QUITS it $m/pane/<n>/errors write-only: text appended to the +Errors pane of the pane's directory $m/os/ the host filesystem @@ -145,7 +146,8 @@ made, or the pane it focused or acted on: an open's own last write's, or, on an open that never wrote, the session's last. With other clients about, write and read one open (`exec 3<>$m/look; echo x >&3; cat <&3; exec 3<&-`). Each command line runs once whole, however a mount cuts a big write; a last -line with no newline runs when the open closes. A command that fails is reported in +line with no newline runs when the open closes, and an Edit block still open +then fails there (an `err`, ``unmatched `{'``), changing nothing. A command that fails is reported in the editor, not as a write error, so inspect the resulting pane, index, message or screen; only a malformed line fails the write itself. A word no builtin knows (a typo included) is a command line: written at a terminal at its @@ -406,8 +406,10 @@ whole: a mount cuts a big write at its message size (4 KiB through the kernel's, 8 KiB from a client that asks), anywhere, and each piece comes as a write of its own, so the open keeps a last line with no newline yet, or an Edit block whose text has not ended, until its next write, and runs it -then; what is left when it closes runs at the close. A fragment never runs -on its own. A line or Edit block held past 1 MiB is refused (EINVAL). +then; what is left when it closes runs at the close, where an Edit block +whose `{` or text never ended fails as any unclosed block does (``unmatched +`{'``, logged as an `err`; nothing changes). A fragment never runs on its +own. A line or Edit block held past 1 MiB is refused (EINVAL). 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 @@ -509,7 +511,10 @@ takes in `file:12:5`: `12:5` is the point at line 12, column 5, and it composes like any simple address (`12:5,14:1`, `12:5+#3`). The column is in bytes from 1, as Look's is, clamped to the end of the line and snapped back to the start of the rune it falls in; a line past the end, or -column 0, is `address out of range`. sam would read `12:5` as a syntax +column 0, is `address out of range`. Since the column counts bytes, a +column a tool gives in characters (pytest's, a compiler's) is the same +only on an ASCII line; elsewhere address the line and search it +(`12/name/`) or use `#n`. sam would read `12:5` as a syntax error. Truncating `data` or `xdata` deletes the range `addr` names and nothing else, so a shell's `echo NEW > data` replaces that range, `: > data` diff --git a/src/ninep/tree.zig b/src/ninep/tree.zig index 414a0b6e..f45a1a90 100644 --- a/src/ninep/tree.zig +++ b/src/ninep/tree.zig @@ -1522,3 +1522,14 @@ test "no placement leaves a pane shorter than its tag and two rows; a full colum try testing.expect(p.rects[k].h >= p.panes[k].?.tag_rows + pardes.layout.min_body_rows); }; } + +test "an Edit block still open when its open closes fails there with an err and changes nothing" { + const p = try th.withFile(testing.allocator, "abc\n"); + defer p.deinit(); + const ctl_node = Node.of(serialOf(p), .ctl); + const c = call(p, .{ .tag = 1, .op = .open, .node = ctl_node, .omode = 1 }).reply.handle; + _ = call(p, .{ .tag = 2, .op = .write, .node = ctl_node, .handle = c, .data = "Edit ,x/b/{\ni/[/\n" }); + _ = call(p, .{ .tag = 3, .op = .release, .node = ctl_node, .handle = c, .opened = true }); + try testing.expect(th.logHas(p, "unmatched")); + try testing.expectEqualStrings("abc\n", p.panes[0].?.file.?.content); +} |
