summaryrefslogtreecommitdiff
path: root/src/pardes.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-20 00:36:50 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commitc1990b3e6e196ad41379aa432bf3ccca8a65d9f0 (patch)
treed7ad5afe559f7f56464b14c3122242fa3f16399b /src/pardes.zig
parent717afaf3177a2e0925b18ae3445119efe808b129 (diff)
downloadpardes-c1990b3e6e196ad41379aa432bf3ccca8a65d9f0.tar.gz
pardes-c1990b3e6e196ad41379aa432bf3ccca8a65d9f0.zip
Flatten the 9P control tree and move it out of fs.zig
The served tree loses the self/ level: /index /ctl /new /log /screen /listeners /pane/<n>/... /os, with /src only in -Dembed-sources=true builds (default off, on for esp32p4). ctl speaks the editor's own language with two lowercase verbs, look TEXT and exec TEXT, plus acme's addr verbs; the new/ factory directory becomes one clone file; cons is gone (exec Msg); name and sel are files; stats report real lengths, modes and mtimes; /log streams pane new/del/rename/save events. The tree code lives in src/ninep/ (tree, pane, ctl, addr, pty, events, screen, sources); fs.zig keeps host access, mounts, resolution and find/grep. Same engine and transports. README (fs-help.txt) and docs rewritten; tests updated and extended. Co-Authored-By: Claude Fable 5.1 <[email protected]>
Diffstat (limited to 'src/pardes.zig')
-rw-r--r--src/pardes.zig34
1 files changed, 20 insertions, 14 deletions
diff --git a/src/pardes.zig b/src/pardes.zig
index 5c0ac263..88442542 100644
--- a/src/pardes.zig
+++ b/src/pardes.zig
@@ -6,6 +6,7 @@ const mvzr = @import("mvzr");
pub const modal = @import("modal.zig");
pub const look = @import("look.zig");
pub const filesystem = @import("fs.zig");
+pub const ctlfs = @import("ninep/tree.zig");
pub const syntax = @import("syntax.zig");
pub const locations_config = @import("locations_config.zig");
const tracy = @import("tracy.zig");
@@ -4711,7 +4712,7 @@ pub const Event = union(enum) {
/// this must not clamp onto and preview the final grid cell.
pointer_leave,
tick,
- fs_req: filesystem.Req,
+ fs_req: ctlfs.Req,
};
pub const attach_name_max = 256;
@@ -4749,7 +4750,7 @@ pub const Effect = union(enum) {
/// Write the build-time theme ring below the per-user config directory.
/// The pane receives the completion/error message from the native host.
dump_themes: struct { pane: u8 },
- fs_reply: filesystem.Reply,
+ fs_reply: ctlfs.Reply,
attach: struct { pane: u8, name: Buf(attach_name_max) },
detach: struct { pane: u8 },
quit,
@@ -6109,6 +6110,7 @@ pub const Pardes = struct {
.fallback = .{ .gpa = gpa },
};
errdefer p.deinit();
+ p.fs.started = ctlfs.events.now();
for (opts.mounts) |mount| try p.fs.mount(gpa, mount.name, mount.dial);
p.opts.mounts = &.{};
p.opts.ninep_identity = .{};
@@ -6335,6 +6337,7 @@ pub const Pardes = struct {
const watched = (if (pane.file) |f| f.output == null else false) or pane.hasPdf();
for (p.panes, 0..) |slot, id| if (slot == pane) {
if (watched) p.emit(.{ .watch = .{ .pane = @intCast(id), .on = false } });
+ ctlfs.events.noteRetire(p, id, pane);
p.fs.forget(p.gpa, id);
// ...and so do bytes still queued for the pty it no longer has.
p.dropPendingWrite(id);
@@ -6380,6 +6383,7 @@ pub const Pardes = struct {
pane.serial = p.next_serial;
p.rects[id] = .{};
p.panes[id] = pane;
+ ctlfs.events.noteInstall(p, id);
}
pub fn newShell(p: *Pardes, id: usize, cwd: []const u8) !*Pane {
@@ -6924,7 +6928,7 @@ pub const Pardes = struct {
return pane.pdfPath();
}
- pub fn fsPayload(p: *const Pardes, r: filesystem.Reply) []const u8 {
+ pub fn fsPayload(p: *const Pardes, r: ctlfs.Reply) []const u8 {
return switch (r.payload) {
.none => &.{},
.staged => |n| p.fs.out.items[0..@min(n, p.fs.out.items.len)],
@@ -6961,6 +6965,7 @@ pub const Pardes = struct {
p.hostWriteFile(sf.pane, f.path, f.content);
const saved_pane = p.panes[sf.pane] orelse return;
if (saved_pane.serial != serial) return;
+ ctlfs.events.noteLog(p, .save, saved_pane);
const saved = if (saved_pane.file) |*file| file else return;
if (saved.saved_revision != saved.revision or !saved.watch_after_save) return;
saved.watch_after_save = false;
@@ -7116,7 +7121,7 @@ pub const Pardes = struct {
},
.output => |o| {
const pane = p.panes[o.pane] orelse return;
- filesystem.notePtyOutput(p, o.pane, o.bytes);
+ ctlfs.events.notePtyOutput(p, o.pane, o.bytes);
panes.Terminal.feedOutput(p, pane, o.bytes);
},
.eof => |e| p.removePane(e.pane) catch |err| {
@@ -7146,7 +7151,7 @@ pub const Pardes = struct {
},
.paste => |bytes| p.applyPaste(bytes),
.command => |line| _ = p.executeBuiltinLine(p.active, line),
- .fs_req => |r| p.emit(.{ .fs_reply = filesystem.handle(p, r) }),
+ .fs_req => |r| p.emit(.{ .fs_reply = ctlfs.handle(p, r) }),
.pinch => |scale| p.ov_pinch_scale = scale,
.touch_scroll => |delta| p.ov_touch_scroll_delta = delta,
.pointer_leave => {
@@ -7163,6 +7168,7 @@ pub const Pardes = struct {
_ = p.scratch.reset(.retain_capacity);
p.sync();
p.fsReport();
+ ctlfs.events.announce(p);
}
fn fsReport(p: *Pardes) void {
@@ -7174,7 +7180,7 @@ pub const Pardes = struct {
const snap = &p.fs.panes[id].tag_snap;
if (std.mem.eql(u8, snap.items, tag)) continue;
if (snap.capacity != 0 or snap.items.len != 0)
- filesystem.noteReplace(p, id, true, snap.items, tag);
+ ctlfs.events.noteReplace(p, id, true, snap.items, tag);
snap.clearRetainingCapacity();
snap.appendSlice(p.gpa, tag) catch {};
}
@@ -7451,7 +7457,7 @@ pub const Pardes = struct {
p.reportError(id, "name", err);
return false;
};
- filesystem.nameBuffer(p, id, full, true) catch |err| {
+ ctlfs.pane.nameBuffer(p, id, full, true) catch |err| {
p.reportError(id, "name", err);
return false;
};
@@ -11673,21 +11679,21 @@ pub const Pardes = struct {
) bool {
if (!p.fs.scripted(id)) return false;
const is_look = cmd == config.look_cmd;
- const action: filesystem.Action = if (is_look)
+ const action: ctlfs.events.Action = if (is_look)
(if (on_tag) .tag_look else .body_look)
else
(if (on_tag) .tag_exec else .body_exec);
const named = std.meta.stringToEnum(Builtin, commandText(text)) != null;
const range = p.gestureRange(id, text, on_tag, operand);
- var flag: u32 = if (named) filesystem.flag_builtin else 0;
- if (range.q0 == range.q1 and text.len > 0) flag |= filesystem.flag_expansion;
+ var flag: u32 = if (named) ctlfs.events.flag_builtin else 0;
+ if (range.q0 == range.q1 and text.len > 0) flag |= ctlfs.events.flag_expansion;
if (is_look) {
- if (!named and std.mem.indexOfAny(u8, text, "/.:") != null) flag |= filesystem.flag_filename;
- } else if (chorded) flag |= filesystem.flag_chorded;
- return filesystem.noteAction(p, id, action, range.q0, range.q1, flag, text);
+ if (!named and std.mem.indexOfAny(u8, text, "/.:") != null) flag |= ctlfs.events.flag_filename;
+ } else if (chorded) flag |= ctlfs.events.flag_chorded;
+ return ctlfs.events.noteAction(p, id, action, range.q0, range.q1, flag, text);
}
- fn gestureRange(p: *Pardes, id: usize, text: []const u8, on_tag: bool, operand: PointerOperand) filesystem.PaneState.Range {
+ fn gestureRange(p: *Pardes, id: usize, text: []const u8, on_tag: bool, operand: PointerOperand) ctlfs.pane.State.Range {
const pane = p.panes[id] orelse return .{};
if (on_tag) {
const tag = p.tagText(p.scratch.allocator(), pane) catch return .{};