summaryrefslogtreecommitdiff
path: root/src/ninep/ctl.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-29 00:50:45 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:15 -0300
commit7aa057e29b729ad6d9ac53e3a06f99858fc449e4 (patch)
treea0010efb342018f32f98d9e805680306feb88836 /src/ninep/ctl.zig
parente563be42a5b3e9243e2c01d34cf8e94d2047b753 (diff)
downloadpardes-7aa057e29b729ad6d9ac53e3a06f99858fc449e4.tar.gz
pardes-7aa057e29b729ad6d9ac53e3a06f99858fc449e4.zip
A column has a ctl, an exec and an rmdir over 9P, and Restore maps its serial
A script could read and write a column's tag but not act on the column. col/<serial>/ctl takes Delcol, Joincol, New and Tty, each acting on that column as from its tag; col/<serial>/exec runs a word as a middle click in the tag; rmdir col/<serial> closes an empty column and refuses one with panes (ENOTEMPTY, an err record saying why). The root ctl's refusal of Delcol and Joincol points at col/<serial>/ctl. A dump keeps each column's serial and Restore logs restoredcol <old> <new>; the dump golden gains them. Documented: Joincol's survivor, the column on the right, keeps its serial and tag. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/ninep/ctl.zig')
-rw-r--r--src/ninep/ctl.zig11
1 files changed, 8 insertions, 3 deletions
diff --git a/src/ninep/ctl.zig b/src/ninep/ctl.zig
index 98120555..e1dd3fc5 100644
--- a/src/ninep/ctl.zig
+++ b/src/ninep/ctl.zig
@@ -51,7 +51,7 @@ fn noteResult(p: *Pardes, serial: u32) void {
/// Runs one look or exec from the pane `id`, then records the panes it
/// created; failing that, a look records the pane it focused and an exec
/// the pane it acted on (even one it closed).
-fn run(p: *Pardes, id: usize, exec: bool, text: []const u8) void {
+pub fn run(p: *Pardes, id: usize, exec: bool, text: []const u8) void {
const context = p.panes[id].?.serial;
// A pane an event reader holds hears its clicks instead of acting on
// them (editors/acme/look.c:53 and exec.c:173 send them to winevent),
@@ -277,7 +277,12 @@ fn checkBuiltin(p: *Pardes, req: Req, line: []const u8, scope: builtins.Scope) ?
};
// Edit is the one pane word the root takes too: at the active pane.
if (builtins.registry.scope(b) != scope and b != .Edit)
- return refuseTo(p, req, if (scope == .pane) "not a window control message" else "not a session control message", line, if (scope == .pane) "/ctl" else "pane/<n>/ctl");
+ return refuseTo(p, req, if (scope == .pane) "not a window control message" else "not a session control message", line, if (scope == .pane)
+ "/ctl"
+ else if (b == .Delcol or b == .Joincol)
+ "col/<serial>/ctl" // a column's own ctl, the one /layout names
+ else
+ "pane/<n>/ctl");
if (arg.len > 0 and !builtins.registry.takesArg(b)) return refuse(p, req, "wrong #args in control message", line);
if (arg.len == 0 and builtins.registry.requiresArg(b)) return refuse(p, req, "wrong #args in control message", line);
const setting = config.Runtime.find(word) orelse return null;
@@ -308,7 +313,7 @@ fn checkBuiltin(p: *Pardes, req: Req, line: []const u8, scope: builtins.Scope) ?
/// would. Answers the refusal when it would have opened a prompt for an
/// argument, which nobody writing to a file is there to type, or when it
/// reported an error: `Mount: AlreadyMounted "Mount peer /tmp/s"`.
-fn runBuiltin(p: *Pardes, req: Req, id: usize, line: []const u8) ?Reply {
+pub fn runBuiltin(p: *Pardes, req: Req, id: usize, line: []const u8) ?Reply {
p.fs.no_prompt = true;
p.fs.refused = false;
p.fs.failure_len = 0;