From 87bb23d39df92db0b383dd300a9ebd1ad9cb2b7a Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Mon, 28 Sep 2026 10:13:45 -0300 Subject: Focus gives the keyboard only, reads empty while a header has it, and sits in the root listing's natural place A write to /focus leaves a folded pane folded, as rio keeps current apart from unhide; while a column or workspace tag has the keyboard no pane does, so /focus reads empty and every pane's ctl says notcurrent (an empty read also no longer answers stale staged bytes). focus, ctl and commands now list after status, and the discovery test checks the root as a set rather than by position. Co-Authored-By: Claude Opus 5.5 --- src/ninep/tree.zig | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'src/ninep/tree.zig') diff --git a/src/ninep/tree.zig b/src/ninep/tree.zig index 27ad02c8..e9c6b8ea 100644 --- a/src/ninep/tree.zig +++ b/src/ninep/tree.zig @@ -438,6 +438,7 @@ fn topSize(p: *Pardes, f: TopFile) u64 { .ctl => ctl.rootLen(p), .commands => ctl.commandsLen(), .focus => focus: { + if (p.header_focus) break :focus 0; const pn = p.panes[p.active] orelse break :focus 0; var digits: [16]u8 = undefined; break :focus (std.fmt.bufPrint(&digits, "{d}\n", .{pn.serial}) catch unreachable).len; @@ -516,14 +517,12 @@ fn readdir(p: *Pardes, req: Req, target: Target) Reply { switch (target) { .top => |f| switch (f) { .root => { - inline for (.{ TopFile.README, TopFile.index, TopFile.status, TopFile.look, TopFile.exec, TopFile.log, TopFile.screen, TopFile.listeners, TopFile.pane }) |t| { + // The guide, then what describes the session, then the + // files that act, then the directories. + inline for (.{ TopFile.README, TopFile.index, TopFile.status, TopFile.focus, TopFile.ctl, TopFile.commands, TopFile.look, TopFile.exec, TopFile.log, TopFile.screen, TopFile.listeners, TopFile.pane }) |t| { if (skip > 0) skip -= 1 else stageDirent(out, p.gpa, @intFromEnum(t), t.dir(), t.fileName()); } if (skip > 0) skip -= 1 else stageDirent(out, p.gpa, fs.os_root, true, "os"); - // After the first ten, which older clients list by position. - inline for (.{ TopFile.focus, TopFile.ctl, TopFile.commands }) |t| { - if (skip > 0) skip -= 1 else stageDirent(out, p.gpa, @intFromEnum(t), t.dir(), t.fileName()); - } sources.stage(p, out, "", &skip); }, .pane => { @@ -901,13 +900,12 @@ test "readdir lists the root and a pane directory without creating anything" { @memcpy(top_bytes[0..top_reply.bytes.len], top_reply.bytes); const top = th.dirents(top_bytes[0..top_reply.bytes.len], &buf); try testing.expect(top.len >= 10); - for ([_][]const u8{ "README", "index", "status", "look", "exec", "log", "screen", "listeners", "pane", "os" }, 0..) |name, i| { + for ([_][]const u8{ "README", "index", "status", "focus", "ctl", "commands", "look", "exec", "log", "screen", "listeners", "pane", "os" }, 0..) |name, i| { try testing.expectEqualStrings(name, top[i].name); - try testing.expectEqual(i >= 8, top[i].dir); + try testing.expectEqual(i >= 11, top[i].dir); } - try testing.expectEqual(@intFromEnum(TopFile.pane), top[8].node); - try testing.expectEqual(fs.os_root, top[9].node); - try testing.expectEqualStrings("focus", top[10].name); + try testing.expectEqual(@intFromEnum(TopFile.pane), top[11].node); + try testing.expectEqual(fs.os_root, top[12].node); var idbuf: [16]u8 = undefined; try testing.expect(th.nameAt(top, try std.fmt.bufPrint(&idbuf, "{d}", .{serial})) == null); try testing.expect(th.nameAt(top, "self") == null); -- cgit v1.3