diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-29 05:20:13 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:16 -0300 |
| commit | 5002c612298fe645791218059a69d2bc80a42d2d (patch) | |
| tree | 1c3ea64ea9b18f8c4f3f67508520f41fd758119e /src | |
| parent | c27e38eb3e97fd505255ee4b42d32ddc77c58ced (diff) | |
| download | pardes-5002c612298fe645791218059a69d2bc80a42d2d.tar.gz pardes-5002c612298fe645791218059a69d2bc80a42d2d.zip | |
Newcol at the column cap says so, and a desktop session holds 16 columns
Newcol with every column slot taken, or a column too narrow to split,
did nothing and said nothing. It now fails (a ctl write with it) with no
space for a column: 16 max (ENOSPC through 9ns), or that the column is
too narrow. MAX_COLS is 16 on a desktop, 6 on the board; each column
costs about 8 KB of core state (the Pardes struct grows from 1.47 MB to
1.56 MB), most of it its tag's text. fs.md and the skill give the cap.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src')
| -rw-r--r-- | src/ninep/ctl.zig | 22 | ||||
| -rw-r--r-- | src/pardes.zig | 13 |
2 files changed, 33 insertions, 2 deletions
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig index 307921b9..3282c743 100644 --- a/src/ninep/ctl.zig +++ b/src/ninep/ctl.zig @@ -1721,3 +1721,25 @@ test "each word's /commands description is its own doc comment's first sentence, try testing.expect(std.mem.indexOf(u8, source[block_start..at], head) != null); } } + +test "Newcol at the column cap fails the write and says the cap" { + const p = try withFile(testing.allocator, "x\n"); + defer p.deinit(); + p.update(.{ .resize = .{ .cols = 4000, .rows = 30 } }); + const root_ctl = @intFromEnum(tree.TopFile.ctl); + while (p.ncol < pardes.MAX_COLS) { + // From the widest column's tag, so no column gets too narrow first. + p.sync(); + var widest: usize = 0; + for (0..p.ncol) |c| if (p.col_w[c] > p.col_w[widest]) { + widest = c; + }; + pardes.tagline.enterHeader(p, widest); + try testing.expectEqual(Status.ok, wr(p, root_ctl, "Newcol\n").reply.status); + } + const refused = wr(p, root_ctl, "Newcol\n"); + try testing.expectEqual(Status.err, refused.reply.status); + var want: [64]u8 = undefined; + try testing.expect(std.mem.indexOf(u8, refused.reply.ename, try std.fmt.bufPrint(&want, "no space for a column: {d} max", .{pardes.MAX_COLS})) != null); + try testing.expect(th.logHas(p, "no space for a column")); +} diff --git a/src/pardes.zig b/src/pardes.zig index b488ec1c..9f192004 100644 --- a/src/pardes.zig +++ b/src/pardes.zig @@ -267,7 +267,9 @@ pub const MAX_TAG_ROWS = 8; pub const MAX_TAG_LAYERS = MAX_PANES + MAX_COLS + 1 + MAX_PANES * Pane.Notices.max; pub const NOTICE_LAYER_BASE = MAX_PANES + MAX_COLS + 1; pub const PDF_PAGE_GAP_PX = panes.Pdf.page_gap_px; -pub const MAX_COLS = 6; +/// Columns a session holds: 16 on a desktop (each costs about 8 KB of state, +/// a column tag being most of it), 6 on the board. +pub const MAX_COLS = if (platform == .esp32p4) 6 else 16; const column_weight_unit = layout.column_weight_unit; const max_column_weight = layout.max_column_weight; pub const MAX_JUMPS = 64; @@ -4849,7 +4851,14 @@ pub const Pardes = struct { /// on its tag, for the next pane made to fill. pub fn newColumn(p: *Pardes, from_id: usize) void { const col = p.keyboardColumn(from_id) orelse return; - const c = layout.insertColumn(p, col, false) orelse return; + // Said, not silently nothing: "no space" is 9ns's word for ENOSPC. + const c = layout.insertColumn(p, col, false) orelse { + var said: [96]u8 = undefined; + return p.reportFailure(from_id, if (p.ncol >= MAX_COLS) + std.fmt.bufPrint(&said, "Newcol: no space for a column: {d} max", .{MAX_COLS}) catch "Newcol: no space for a column" + else + "Newcol: no space for a column: this one is too narrow to split"); + }; tagline.enterHeader(p, c); } |
