summaryrefslogtreecommitdiff
path: root/src/ninep/ctl.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/ninep/ctl.zig')
-rw-r--r--src/ninep/ctl.zig27
1 files changed, 23 insertions, 4 deletions
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index e47dec16..4afc82dc 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -12,6 +12,7 @@ const panes = @import("../panes.zig");
const config = @import("../config.zig");
const fs = @import("../fs.zig");
const tagline = @import("../tagline.zig");
+const layout = @import("../layout.zig");
const builtins = @import("../builtins.zig");
const exec_line = @import("../exec.zig");
const tree = @import("tree.zig");
@@ -162,7 +163,9 @@ pub fn paneText(p: *Pardes, pane: *Pane, buf: []u8) []const u8 {
}) catch return w.buffered();
const font = p.settings.font.effective_name.get();
writeQuoted(&w, if (font.len == 0) "default" else font) catch return w.buffered();
- w.print(" {d:>11} {s} ", .{ config.tab_width, if (p.panes[p.active] == pane) "current" else "notcurrent" }) catch {};
+ // While a column's or the workspace's tag has the keyboard, no pane does.
+ const current = p.panes[p.active] == pane and !p.header_focus;
+ w.print(" {d:>11} {s} ", .{ config.tab_width, if (current) "current" else "notcurrent" }) catch {};
return w.buffered();
}
@@ -333,10 +336,15 @@ pub fn readCommands(p: *Pardes, req: Req) Reply {
// ---- /focus ----
/// The pane with the keyboard, which a write of a serial moves, the way
-/// writing `current` to rio's wctl does (rio(4)).
+/// writing `current` to rio's wctl does (rio(4)). While a column's or the
+/// workspace's tag has it, no pane does, and this reads empty. A write
+/// gives the keyboard and nothing else: a folded pane stays folded, as
+/// rio keeps `current` apart from `unhide`.
pub fn readFocus(p: *Pardes, req: Req) Reply {
+ const out = p.fs.stage(p.gpa);
+ if (p.header_focus) return tree.stagedReply(p, req);
const pane = p.panes[p.active] orelse return tree.stagedReply(p, req);
- p.fs.stage(p.gpa).print(p.gpa, "{d}\n", .{pane.serial}) catch return Reply.fail(req.tag, E.NOMEM);
+ out.print(p.gpa, "{d}\n", .{pane.serial}) catch return Reply.fail(req.tag, E.NOMEM);
return tree.stagedReply(p, req);
}
@@ -506,8 +514,11 @@ test "focus reads the pane with the keyboard, and a serial written to it moves t
try testing.expectEqual(@as(u64, rd(p, focus, 0, 64).bytes.len), call(p, .{ .tag = 1, .op = .getattr, .node = focus }).reply.attr.size);
try testing.expect(std.mem.endsWith(u8, rd(p, Node.of(first, .ctl), 0, 4096).bytes, " notcurrent "));
- // A header had the keyboard: the write takes it back to the pane.
+ // A header has the keyboard: no pane does, and a write takes it back.
tagline.enterHeader(p, null);
+ try testing.expectEqualStrings("", rd(p, focus, 0, 64).bytes);
+ try testing.expectEqual(@as(u64, 0), call(p, .{ .tag = 1, .op = .getattr, .node = focus }).reply.attr.size);
+ try testing.expect(std.mem.endsWith(u8, rd(p, Node.of(second, .ctl), 0, 4096).bytes, " notcurrent "));
try testing.expectEqual(Status.ok, wr(p, focus, try std.fmt.bufPrint(&line, "{d}\n", .{first})).reply.status);
try testing.expect(!p.header_focus);
try testing.expectEqual(p.paneBySerial(first).?, p.active);
@@ -518,6 +529,14 @@ test "focus reads the pane with the keyboard, and a serial written to it moves t
try testing.expectEqual(E.NOENT, wr(p, focus, "99999").errno());
for ([_][]const u8{ "", "two", "-1", "1 2" }) |bad| try testing.expectEqual(E.INVAL, wr(p, focus, bad).errno());
try testing.expectEqual(p.paneBySerial(first).?, p.active);
+
+ // Focus gives the keyboard only: a folded pane stays folded.
+ const folded = p.paneBySerial(second).?;
+ layout.toggleCollapse(p, folded);
+ try testing.expect(p.panes[folded].?.collapsed);
+ try testing.expectEqual(Status.ok, wr(p, focus, try std.fmt.bufPrint(&line, "{d}", .{second})).reply.status);
+ try testing.expectEqual(folded, p.active);
+ try testing.expect(p.panes[folded].?.collapsed);
}
test "the pane ctl takes acme's verbs and the pane's builtins, and refuses the rest in Plan 9's words" {