summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-29 03:14:45 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:15 -0300
commit7fe3a1d9a9ee3c2510ecac40e079608447eead70 (patch)
tree01cf469853198f2def268745254253a786c34718
parenta7960117dfb83ad65a0466a96affbbb524936b7f (diff)
downloadpardes-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.md6
-rw-r--r--docs/fs.md11
-rw-r--r--src/ninep/tree.zig11
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
diff --git a/docs/fs.md b/docs/fs.md
index 80735642..cf6acb60 100644
--- a/docs/fs.md
+++ b/docs/fs.md
@@ -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);
+}