summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/detached/server.zig42
-rw-r--r--src/gui/gui.zig45
-rw-r--r--src/host_io.zig52
-rw-r--r--src/tty/tty.zig26
4 files changed, 66 insertions, 99 deletions
diff --git a/src/detached/server.zig b/src/detached/server.zig
index de26db13..d8379793 100644
--- a/src/detached/server.zig
+++ b/src/detached/server.zig
@@ -587,24 +587,11 @@ pub const Session = struct {
fn writeFile(ctx: ?*anyopaque, pane: u8, path: []const u8, bytes: []const u8) void {
const s = of(ctx);
- filesystem.write(s.core, path, bytes) catch |err|
- return s.core.saveFailed(pane, path, err);
- if (s.core.panes[pane]) |pn| if (pn.file) |f| if (std.mem.eql(u8, f.path, path)) {
- if (s.watches[pane]) |*w| if (w.serial == pn.serial) switch (w.generation) {
- .text => w.generation = .{ .text = std.hash.Wyhash.hash(0, bytes) },
- .pdf => {},
- };
- };
- var mbuf: [256]u8 = undefined;
- s.core.setMessage(pane, message.stamp(&mbuf, "saved", path));
+ host_io.writeFile(s.core, &s.watches, pane, path, bytes);
}
fn writeDump(ctx: ?*anyopaque, bytes: []const u8) void {
- const s = of(ctx);
- var pbuf: [1024:0]u8 = undefined;
- const path = pardes.dump.outPath(&pbuf, s.core.settings.dump_dir.get()) orelse return s.core.dumpFailed(s.core.settings.dump_dir.get(), error.NoDumpDirectory);
- filesystem.write(s.core, path, bytes) catch |err| return s.core.dumpFailed(path, err);
- s.core.setLastDump(path);
+ host_io.writeDump(of(ctx).core, bytes);
}
fn watchFile(ctx: ?*anyopaque, pane: u8, _: []const u8, on: bool, mode: pardes.WatchMode) void {
@@ -621,14 +608,7 @@ pub const Session = struct {
fn dumpThemes(ctx: ?*anyopaque, pane: u8) void {
const s = of(ctx);
- const config_dir = s.core.opts.config_dir orelse return;
- const out_dir = pardes.config.User.dumpThemes(s.io, s.gpa, config_dir, pardes.themes) catch |err| {
- s.core.reportError(pane, "dump themes", err);
- return;
- };
- defer s.gpa.free(out_dir);
- var mbuf: [256]u8 = undefined;
- s.core.setMessage(pane, message.stamp(&mbuf, "dumped themes", out_dir));
+ host_io.dumpThemes(s.core, s.io, s.gpa, pane);
}
fn setClipboard(ctx: ?*anyopaque, text: []const u8) void {
@@ -761,20 +741,8 @@ pub const Session = struct {
fn harvest(s: *Session) void {
const now = monotonicMs();
- for (&s.retired_shells) |*shell| reapShell(&shell.pid, &shell.kill_at, now);
- for (&s.ptys) |*pty| if (pty.fd < 0) reapShell(&pty.pid, &pty.kill_at, now);
- }
-
- fn reapShell(pid: *posix.pid_t, kill_at: *i64, now: i64) void {
- if (pid.* == 0) return;
- const result = libc.waitpid(pid.*, null, libc.W.NOHANG);
- if (result > 0 or (result < 0 and libc.errno(result) == .CHILD)) {
- pid.* = 0;
- kill_at.* = 0;
- } else if (kill_at.* != 0 and now >= kill_at.*) {
- _ = libc.kill(pid.*, libc.SIG.KILL);
- kill_at.* = 0;
- }
+ for (&s.retired_shells) |*shell| host_io.reapRetired(&shell.pid, &shell.kill_at, now);
+ for (&s.ptys) |*pty| if (pty.fd < 0) host_io.reapRetired(&pty.pid, &pty.kill_at, now);
}
fn inotify(s: *Session) c_int {
diff --git a/src/gui/gui.zig b/src/gui/gui.zig
index 8b100cd8..8fd8d360 100644
--- a/src/gui/gui.zig
+++ b/src/gui/gui.zig
@@ -4060,9 +4060,9 @@ const Shell = struct {
fn reap(s: *Shell) void {
const now = shellClock();
- for (&s.retired_shells) |*child| reapShell(&child.pid, &child.kill_at, now);
+ for (&s.retired_shells) |*child| host_io.reapRetired(&child.pid, &child.kill_at, now);
for (s.ptys) |*slot| if (slot.*) |*pt| if (pt.fd < 0) {
- reapShell(&pt.pid, &pt.kill_at, now);
+ host_io.reapRetired(&pt.pid, &pt.kill_at, now);
if (pt.pid == 0) slot.* = null;
};
}
@@ -4085,7 +4085,7 @@ const Shell = struct {
_ = libc.close(pt.fd);
pt.fd = -1;
const now = shellClock();
- reapShell(&pt.pid, &pt.kill_at, now);
+ host_io.reapRetired(&pt.pid, &pt.kill_at, now);
if (pt.pid == 0) {
s.ptys[pane] = null;
return;
@@ -4662,25 +4662,11 @@ fn killJob(ctx: ?*anyopaque, pane: u8) bool {
fn writeFile(ctx: ?*anyopaque, pane: u8, path: []const u8, bytes: []const u8) void {
const s = shellOf(ctx);
- filesystem.write(s.core, path, bytes) catch |err|
- return s.core.saveFailed(pane, path, err);
- if (s.core.panes[pane]) |pane_state| if (pane_state.file) |f| {
- if (std.mem.eql(u8, f.path, path))
- if (s.watches[pane]) |*w| if (w.serial == pane_state.serial) switch (w.generation) {
- .text => w.generation = .{ .text = std.hash.Wyhash.hash(0, bytes) },
- .pdf => {},
- };
- };
- var mbuf: [256]u8 = undefined;
- s.core.setMessage(pane, message.stamp(&mbuf, "saved", path));
+ host_io.writeFile(s.core, s.watches, pane, path, bytes);
}
fn writeDump(ctx: ?*anyopaque, bytes: []const u8) void {
- const s = shellOf(ctx);
- var pbuf: [1024:0]u8 = undefined;
- const path = pardes.dump.outPath(&pbuf, s.core.settings.dump_dir.get()) orelse return s.core.dumpFailed(s.core.settings.dump_dir.get(), error.NoDumpDirectory);
- filesystem.write(s.core, path, bytes) catch |err| return s.core.dumpFailed(path, err);
- s.core.setLastDump(path);
+ host_io.writeDump(shellOf(ctx).core, bytes);
}
fn watchFile(ctx: ?*anyopaque, pane: u8, _: []const u8, on: bool, mode: pardes.WatchMode) void {
@@ -4704,14 +4690,7 @@ fn watchTheme(ctx: ?*anyopaque, generation: u32, on: bool) void {
fn dumpThemes(ctx: ?*anyopaque, pane: u8) void {
const s = shellOf(ctx);
- const config_dir = s.core.opts.config_dir orelse return;
- const out_dir = config.User.dumpThemes(s.io, s.gpa, config_dir, pardes.themes) catch |err| {
- s.core.reportError(pane, "dump themes", err);
- return;
- };
- defer s.gpa.free(out_dir);
- var mbuf: [256]u8 = undefined;
- s.core.setMessage(pane, message.stamp(&mbuf, "dumped themes", out_dir));
+ host_io.dumpThemes(s.core, s.io, s.gpa, pane);
}
fn putClipboard(gpa: std.mem.Allocator, text: []const u8) void {
@@ -4826,18 +4805,6 @@ fn shellClock() i64 {
return @as(i64, ts.sec) * std.time.ms_per_s + @divTrunc(ts.nsec, std.time.ns_per_ms);
}
-fn reapShell(pid: *libc.pid_t, kill_at: *i64, now: i64) void {
- if (pid.* <= 0) return;
- const result = libc.waitpid(pid.*, null, libc.W.NOHANG);
- if (result > 0 or (result < 0 and libc.errno(result) == .CHILD)) {
- pid.* = 0;
- kill_at.* = 0;
- } else if (kill_at.* != 0 and now >= kill_at.*) {
- _ = libc.kill(pid.*, libc.SIG.KILL);
- kill_at.* = 0;
- }
-}
-
fn accumulateWheelDelta(pending: f32, raw_y: f32) f32 {
if (!std.math.isFinite(raw_y)) return pending;
const next = pending - raw_y;
diff --git a/src/host_io.zig b/src/host_io.zig
index 05ccca09..ac25e63c 100644
--- a/src/host_io.zig
+++ b/src/host_io.zig
@@ -5,6 +5,7 @@ const libc = std.c;
const pardes = @import("pardes.zig");
const ninep_io = @import("9p_io.zig");
const filesystem = @import("fs.zig");
+const file_watch = @import("file_watch.zig");
pub const Host = struct {
ctx: ?*anyopaque = null,
@@ -2522,3 +2523,54 @@ test "a full-screen program takes the tty until it quits" {
}
if (ran == 0) return error.SkipZigTest;
}
+
+// ---- what every host's vtable does alike ----
+
+/// A Save's write: the file written through the core's filesystem, the
+/// pane's watch told the new text is the editor's own (so it is no outside
+/// change), and "saved" said on the pane.
+pub fn writeFile(core: *pardes.Pardes, watches: *file_watch.Table, pane: u8, path: []const u8, bytes: []const u8) void {
+ filesystem.write(core, path, bytes) catch |err|
+ return core.saveFailed(pane, path, err);
+ if (core.panes[pane]) |pn| if (pn.file) |f| if (std.mem.eql(u8, f.path, path)) {
+ if (watches[pane]) |*w| if (w.serial == pn.serial) switch (w.generation) {
+ .text => w.generation = .{ .text = std.hash.Wyhash.hash(0, bytes) },
+ .pdf => {},
+ };
+ };
+ var mbuf: [256]u8 = undefined;
+ core.setMessage(pane, pardes.Messages.Message.stamp(&mbuf, "saved", path));
+}
+
+/// A Dump's write, into the DumpDir.
+pub fn writeDump(core: *pardes.Pardes, bytes: []const u8) void {
+ var pbuf: [1024:0]u8 = undefined;
+ const path = pardes.dump.outPath(&pbuf, core.settings.dump_dir.get()) orelse return core.dumpFailed(core.settings.dump_dir.get(), error.NoDumpDirectory);
+ filesystem.write(core, path, bytes) catch |err| return core.dumpFailed(path, err);
+ core.setLastDump(path);
+}
+
+/// DumpThemes: the built-in themes written below the config directory.
+pub fn dumpThemes(core: *pardes.Pardes, io: std.Io, gpa: std.mem.Allocator, pane: u8) void {
+ const config_dir = core.opts.config_dir orelse return;
+ const out_dir = pardes.config.User.dumpThemes(io, gpa, config_dir, pardes.themes) catch |err| {
+ core.reportError(pane, "dump themes", err);
+ return;
+ };
+ defer gpa.free(out_dir);
+ var mbuf: [256]u8 = undefined;
+ core.setMessage(pane, pardes.Messages.Message.stamp(&mbuf, "dumped themes", out_dir));
+}
+
+/// A retired shell reaped once it has exited, killed once its grace is up.
+pub fn reapRetired(pid: *std.c.pid_t, kill_at: *i64, now: i64) void {
+ if (pid.* <= 0) return;
+ const result = std.c.waitpid(pid.*, null, std.c.W.NOHANG);
+ if (result > 0 or (result < 0 and std.c.errno(result) == .CHILD)) {
+ pid.* = 0;
+ kill_at.* = 0;
+ } else if (kill_at.* != 0 and now >= kill_at.*) {
+ _ = std.c.kill(pid.*, std.c.SIG.KILL);
+ kill_at.* = 0;
+ }
+}
diff --git a/src/tty/tty.zig b/src/tty/tty.zig
index 3441bc29..ef7f2761 100644
--- a/src/tty/tty.zig
+++ b/src/tty/tty.zig
@@ -1791,24 +1791,11 @@ const Shell = struct {
fn writeFile(ctx: ?*anyopaque, pane: u8, path: []const u8, bytes: []const u8) void {
const s = of(ctx);
- filesystem.write(s.core, path, bytes) catch |err|
- return s.core.saveFailed(pane, path, err);
- if (s.core.panes[pane]) |pn| if (pn.file) |f| if (std.mem.eql(u8, f.path, path)) {
- if (s.watches[pane]) |*w| if (w.serial == pn.serial) switch (w.generation) {
- .text => w.generation = .{ .text = std.hash.Wyhash.hash(0, bytes) },
- .pdf => {},
- };
- };
- var mbuf: [256]u8 = undefined;
- s.core.setMessage(pane, message.stamp(&mbuf, "saved", path));
+ host_io.writeFile(s.core, &s.watches, pane, path, bytes);
}
fn writeDump(ctx: ?*anyopaque, bytes: []const u8) void {
- const s = of(ctx);
- var pbuf: [1024:0]u8 = undefined;
- const path = pardes.dump.outPath(&pbuf, s.core.settings.dump_dir.get()) orelse return s.core.dumpFailed(s.core.settings.dump_dir.get(), error.NoDumpDirectory);
- filesystem.write(s.core, path, bytes) catch |err| return s.core.dumpFailed(path, err);
- s.core.setLastDump(path);
+ host_io.writeDump(of(ctx).core, bytes);
}
fn watchFile(ctx: ?*anyopaque, pane: u8, _: []const u8, on: bool, mode: pardes.WatchMode) void {
@@ -1825,14 +1812,7 @@ const Shell = struct {
fn dumpThemes(ctx: ?*anyopaque, pane: u8) void {
const s = of(ctx);
- const config_dir = s.core.opts.config_dir orelse return;
- const out_dir = pardes.config.User.dumpThemes(s.io, s.gpa, config_dir, pardes.themes) catch |err| {
- s.core.reportError(pane, "dump themes", err);
- return;
- };
- defer s.gpa.free(out_dir);
- var mbuf: [256]u8 = undefined;
- s.core.setMessage(pane, message.stamp(&mbuf, "dumped themes", out_dir));
+ host_io.dumpThemes(s.core, s.io, s.gpa, pane);
}
fn setClipboard(ctx: ?*anyopaque, text: []const u8) void {