diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-29 03:11:42 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:15 -0300 |
| commit | 073695995ecf4a269da8d338b23bfab1d3369c05 (patch) | |
| tree | 0d8e573e509d2462de31cb1f7198dc5e44aabaf2 | |
| parent | cf49c329cb401a5c530ef2533066702fe1545360 (diff) | |
| download | pardes-073695995ecf4a269da8d338b23bfab1d3369c05.tar.gz pardes-073695995ecf4a269da8d338b23bfab1d3369c05.zip | |
+Errors with no room anywhere logs its text rather than fail the Edit
Edit's p and = put their output in +Errors, and when its column had no
room the placement refusal failed the whole Edit. +Errors now tries every
column with room, the last first, and with none its text is logged as msg
records, a line each; the Edit succeeds.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
| -rw-r--r-- | docs/tags.md | 3 | ||||
| -rw-r--r-- | src/exec.zig | 29 | ||||
| -rw-r--r-- | src/ninep/ctl.zig | 13 | ||||
| -rw-r--r-- | src/ninep/pane.zig | 6 |
4 files changed, 48 insertions, 3 deletions
diff --git a/docs/tags.md b/docs/tags.md index 5c4492bc..cee8e335 100644 --- a/docs/tags.md +++ b/docs/tags.md @@ -240,6 +240,9 @@ that room, the column's tallest pane is halved instead; where no pane of the column can give it, the new pane is refused and closed, with `no space for a pane in that column: each keeps its tag and 2 rows` (a 9P write or open of `pane/new` fails with it, ENOSPC). A pane alone in its column always fits. +A `+Errors` pane goes to any column with room, the last first; with none, +what it would have shown (an Edit's `p` or `=`, a write to `errors`) is +logged as `msg` records, a line each, and the Edit still succeeds. `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 diff --git a/src/exec.zig b/src/exec.zig index 0a7e71f9..bb4309a4 100644 --- a/src/exec.zig +++ b/src/exec.zig @@ -851,9 +851,32 @@ pub fn placeNew(p: *Pardes, from: usize, origin: ?usize, id: usize, kind: NewPan layout.snapColWeights(p, f.col); if (!layout.splitTallest(p, f.col, id) or !layout.placedRoomy(p, id, &before)) { if (layout.findPane(p, id) == null) layout.insert(p, f.col, p.col_n[f.col], id); - p.unplaced.set(id); - p.reportError(from, "placement", error.NoPaneRoom); - return; + // +Errors goes wherever there is room, last column first; with + // none, its maker says the text some other way (appendErrors). + if (kind == .errors) { + layout.removePane(p, id); + var c = p.ncol; + while (c > 0) { + c -= 1; + if (c == f.col) continue; + for (p.col_panes[c][0..p.col_n[c]]) |k| p.rects[k] = before[k]; + layout.snapColWeights(p, c); + if (p.col_n[c] == 0) { + layout.insert(p, c, 0, id); + break; + } + if (layout.splitTallest(p, c, id) and layout.placedRoomy(p, id, &before)) break; + if (layout.findPane(p, id) != null) layout.removePane(p, id); + } else { + layout.insert(p, f.col, p.col_n[f.col], id); + p.unplaced.set(id); + return; + } + } else { + p.unplaced.set(id); + p.reportError(from, "placement", error.NoPaneRoom); + return; + } } }; if (kind == .command) return; diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig index 25abd9b5..378dd844 100644 --- a/src/ninep/ctl.zig +++ b/src/ninep/ctl.zig @@ -1447,3 +1447,16 @@ test "an exec line over the command limit fails the write and says the limit; a try testing.expect(th.logHas(p, "a command line is at most 1024 bytes")); try testing.expectEqual(Status.ok, wr(p, root_exec, "Msg " ++ "z" ** 1100 ++ "\n").reply.status); } + +test "Edit's p and = never fail for want of room for +Errors: the text is logged instead" { + const p = try withFile(testing.allocator, "one\ntwo\n"); + defer p.deinit(); + p.update(.{ .resize = .{ .cols = 80, .rows = 6 } }); + const ctl_node = Node.of(serialOf(p), .ctl); + try testing.expectEqual(Status.ok, wr(p, ctl_node, "Edit ,p\n").reply.status); + try testing.expect(th.logHas(p, " one\n") and th.logHas(p, " two\n")); + p.sync(); + var count: usize = 0; + for (p.panes) |slot| count += @intFromBool(slot != null); + try testing.expectEqual(@as(usize, 1), count); // the +Errors that had no room is gone +} diff --git a/src/ninep/pane.zig b/src/ninep/pane.zig index 3307eb47..791cb797 100644 --- a/src/ninep/pane.zig +++ b/src/ninep/pane.zig @@ -649,6 +649,12 @@ pub fn appendErrors(p: *Pardes, id: usize, text: []const u8) ?usize { return null; }; exec.placeNew(p, id, id, free, .errors); + // No column had room for it (it closes at the step's end): the text is + // logged instead, a msg a line, so it is not lost and nothing fails. + if (p.unplaced.isSet(free)) { + var lines = std.mem.splitScalar(u8, std.mem.trimEnd(u8, text, "\n"), '\n'); + while (lines.next()) |line| events.noteMessage(p, pane.serial, line[0..@min(line.len, pardes.Messages.LoggedMessage.cap)]); + } return text.len; } |
