diff options
| author | Robert Günzler <r@gnzler.io> | 2026-01-17 17:17:09 +0100 |
|---|---|---|
| committer | Robert Günzler <r@gnzler.io> | 2026-01-29 21:05:23 +0100 |
| commit | 00e8ec8f029d3fb248139bae366220d5b01e8cd8 (patch) | |
| tree | de1fd513a87f612f58ff0da21a2257e60a38548d | |
| parent | f4dbf77e41f57c394448650690d1bb3b4973c30d (diff) | |
| download | site-00e8ec8f029d3fb248139bae366220d5b01e8cd8.tar.gz | |
fix for zig 0.15
writergate Signed-off-by: Robert Günzler <r@gnzler.io>
| -rw-r--r-- | src/exe.zig | 19 | ||||
| -rw-r--r-- | src/fs.zig | 9 | ||||
| -rw-r--r-- | src/gen.zig | 80 |
3 files changed, 66 insertions, 42 deletions
diff --git a/src/exe.zig b/src/exe.zig index 8624193..4d55c72 100644 --- a/src/exe.zig +++ b/src/exe.zig @@ -82,8 +82,11 @@ fn pandocWorker(ctx: *Context, page: []const u8) !void { const f = try fs.FileSwapper.createAt(ctx.allocator(), target_path); defer f.close(); + var buffer: [1024]u8 = undefined; + var w = f.writer(&buffer); + // open new scope to close the file swapper when we're done writing - try f.writer().print( + try w.interface.print( \\<!-- Generated file, you may edit and discard {s} :) --> \\ , @@ -107,7 +110,7 @@ fn pandocWorker(ctx: *Context, page: []const u8) !void { "--strip-comments", "--output=-", source_path, - }, &env_map, f.writer().any()); + }, &env_map, &w.interface); // swap now, we want to edit mtime try f.swap(); @@ -118,7 +121,7 @@ fn pandocWorker(ctx: *Context, page: []const u8) !void { try fs.setMtime(target_path, mtime); } -pub fn captureStdout(ctx: *Context, argv: []const []const u8, env_map: ?*std.process.EnvMap, buf: std.io.AnyWriter) !void { +pub fn captureStdout(ctx: *Context, argv: []const []const u8, env_map: ?*std.process.EnvMap, w: *std.Io.Writer) !void { const command = try std.mem.join(ctx.allocator(), " ", argv); defer ctx.allocator().free(command); const label = try std.fmt.allocPrint(ctx.allocator(), "running {s}", .{command}); @@ -127,14 +130,22 @@ pub fn captureStdout(ctx: *Context, argv: []const []const u8, env_map: ?*std.pro ctx.progress_start(label); defer ctx.progress_end(); + log.debug("running {s}", .{command}); + var p = std.process.Child.init(argv, std.heap.page_allocator); + p.stdin_behavior = .Ignore; p.stdout_behavior = .Pipe; + p.stderr_behavior = .Ignore; p.progress_node = ctx.progress_nodes.getLast(); p.env_map = env_map; try p.spawn(); - try buf.writeFile(p.stdout.?); + var buffer: [1024]u8 = undefined; + var r = p.stdout.?.readerStreaming(&buffer); + + _ = try w.sendFileAll(&r, .unlimited); + try w.flush(); const result = try p.wait(); _ = result; diff --git a/src/fs.zig b/src/fs.zig index d6c182d..4e42f44 100644 --- a/src/fs.zig +++ b/src/fs.zig @@ -43,8 +43,8 @@ pub const FileSwapper = struct { return self.tmp; } - pub fn writer(self: FileSwapper) std.fs.File.Writer { - return self.tmp.writer(); + pub fn writer(self: FileSwapper, buffer: []u8) std.fs.File.Writer { + return self.tmp.writer(buffer); } pub fn diff(self: FileSwapper) !bool { @@ -133,7 +133,6 @@ pub fn joinPathAndFilename(alloc: std.mem.Allocator, paths: []const []const u8, const filename = try std.mem.concat(fba.allocator(), u8, filename_parts); var p = try std.ArrayList([]const u8).initCapacity(fba.allocator(), paths.len + 1); - defer p.deinit(); p.appendSliceAssumeCapacity(paths); p.appendAssumeCapacity(filename); @@ -171,8 +170,8 @@ pub fn getMtime(path: []const u8) !std.posix.timespec { const fd = try std.fs.cwd().openFile(path, .{ .mode = .read_only }); defer fd.close(); - const meta = try fd.metadata(); - const mtime = meta.modified(); + const meta = try fd.stat(); + const mtime = meta.mtime; return .{ .sec = std.math.cast(isize, @divFloor(mtime, std.time.ns_per_s)) orelse std.math.maxInt(isize), diff --git a/src/gen.zig b/src/gen.zig index 3245e7c..eb768e5 100644 --- a/src/gen.zig +++ b/src/gen.zig @@ -65,7 +65,10 @@ fn genIndex(ctx: *Context) !void { const f = try fs.FileSwapper.createAt(ctx.allocator(), srcpathIndex); defer f.close(); - try f.writer().writeAll( + var buffer: [1024]u8 = undefined; + var w = f.writer(&buffer); + + try w.interface.writeAll( \\<ul class="col2 captial"> \\ ); @@ -89,7 +92,7 @@ fn genIndex(ctx: *Context) !void { const dstpath = try fs.joinPathAndFilename(ctx.allocator(), &.{Context.params.SITE_PATH}, &.{ dstname, ".html" }); defer ctx.allocator().free(dstpath); - try f.writer().print( + try w.interface.print( \\<li><a href="/{[LINK]s}">{[NAME]s}</a></li> \\ , .{ @@ -98,11 +101,13 @@ fn genIndex(ctx: *Context) !void { }); } - try f.writer().writeAll( + try w.interface.writeAll( \\</ul> \\ ); + try w.interface.flush(); + if (!try f.diff()) try f.undo(); } @@ -138,16 +143,19 @@ fn genSite(ctx: *Context) !void { const f = try fs.FileSwapper.createAt(ctx.allocator(), dstpath); defer f.close(); + var buffer: [1024]u8 = undefined; + var w = f.writer(&buffer); + const page_name = try std.mem.replaceOwned(u8, ctx.allocator(), dstname, "_", " "); defer ctx.allocator().free(page_name); - try build(ctx.allocator(), f.writer().any(), page_name, srcpath); + try build(ctx.allocator(), &w.interface, page_name, srcpath); ctx.generated += 1; } } // build a single html file -fn build(allocator: std.mem.Allocator, w: std.io.AnyWriter, page_name: []const u8, srcpath: []const u8) !void { +fn build(allocator: std.mem.Allocator, w: *std.Io.Writer, page_name: []const u8, srcpath: []const u8) !void { const mtime = try fs.getMtime(srcpath); const mtime_str = try fs.formatTimespec(allocator, mtime, "%F"); defer allocator.free(mtime_str); @@ -235,6 +243,8 @@ fn build(allocator: std.mem.Allocator, w: std.io.AnyWriter, page_name: []const u \\</html> \\ ); + + try w.flush(); } // build a virtual html file, currently either: @@ -266,7 +276,10 @@ fn meta(ctx: *Context, p: []const u8) !void { const f = try fs.FileSwapper.createAt(ctx.allocator(), dstpath); defer f.close(); - try f.writer().print( + var buffer: [1024]u8 = undefined; + var w = f.writer(&buffer); + + try w.interface.print( \\<!DOCTYPE html> \\<html lang="en"> \\<head> @@ -287,6 +300,7 @@ fn meta(ctx: *Context, p: []const u8) !void { , .{ .LINK = link, }); + try w.interface.flush(); ctx.tilde += 1; return; @@ -296,7 +310,10 @@ fn meta(ctx: *Context, p: []const u8) !void { } // parses srcpath, resolves refs and portals and writes everything to w -fn inject(allocator: std.mem.Allocator, w: std.io.AnyWriter, srcpath: []const u8) !void { +fn inject(allocator: std.mem.Allocator, w: *std.Io.Writer, srcpath: []const u8) !void { + var arena = std.heap.ArenaAllocator.init(allocator); + defer arena.deinit(); + const inc = std.fs.cwd().openFile(srcpath, .{ .mode = .read_only }) catch |err| { if (err == error.FileNotFound) log.warn("Missing {s} include.", .{srcpath}); @@ -305,30 +322,27 @@ fn inject(allocator: std.mem.Allocator, w: std.io.AnyWriter, srcpath: []const u8 }; defer inc.close(); - var buf_writer = std.io.bufferedWriter(w); - var out_stream = buf_writer.writer(); + var buffer: [1024]u8 = undefined; + var r = inc.readerStreaming(&buffer); - var buf_reader = std.io.bufferedReader(inc.reader()); - var in_stream = buf_reader.reader(); + var chunkw = std.Io.Writer.Allocating.init(arena.allocator()); + defer chunkw.deinit(); - var arena = std.heap.ArenaAllocator.init(allocator); - defer arena.deinit(); + while (true) { + defer chunkw.clearRetainingCapacity(); // reset chunk + + _ = r.interface.streamDelimiter(&chunkw.writer, '\n') catch |err| + if (err == error.EndOfStream) break + else return err; - while (in_stream.readUntilDelimiterOrEofAlloc( - arena.allocator(), - '\n', - buf_reader.buf.len, - ) catch { - @panic("Failed to read from stream"); - }) |chunk_| { - defer _ = arena.reset(.free_all); + _ = r.interface.toss(1); // skip newline delimiter - var chunk = chunk_; + var chunk = chunkw.written(); templating: while (true) { if (std.mem.indexOfPosLinear(u8, chunk, 0, "{")) |start| { if (std.mem.indexOfPosLinear(u8, chunk, start + 1, "}")) |end| { - try out_stream.writeAll(chunk[0..start]); - template(allocator, out_stream.any(), chunk[start + 1 .. end]) catch |err| switch (err) { + try w.writeAll(chunk[0..start]); + template(allocator, w, chunk[start + 1 .. end]) catch |err| switch (err) { error.FileNotFound => { // log.warn("ref {s} not found", .{chunk[start + 1 .. end]}); // trim already written chunk and exit templating @@ -342,16 +356,16 @@ fn inject(allocator: std.mem.Allocator, w: std.io.AnyWriter, srcpath: []const u8 } else break :templating; } - try out_stream.writeAll(chunk); - try out_stream.writeByte('\n'); - try buf_writer.flush(); + try w.writeAll(chunk); + try w.writeByte('\n'); + try w.flush(); } - try buf_writer.flush(); + try w.flush(); } // implements various reference types that can be used in .htm templates -fn template(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8) anyerror!void { +fn template(allocator: std.mem.Allocator, w: *std.Io.Writer, refname: []const u8) anyerror!void { switch (refname[0]) { '/' => return try portal(allocator, w, refname[1..], false), '$' => return try ref_link(allocator, w, refname[1..]), @@ -393,7 +407,7 @@ const Page = struct { } }; -fn portal(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8, insert_heading: bool) anyerror!void { +fn portal(allocator: std.mem.Allocator, w: *std.Io.Writer, refname: []const u8, insert_heading: bool) anyerror!void { const page = try Page.from_ref(allocator, refname); defer page.deinit(); @@ -412,7 +426,7 @@ fn portal(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8 // XXX: track ref count? } -fn ref(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8) anyerror!void { +fn ref(allocator: std.mem.Allocator, w: *std.Io.Writer, refname: []const u8) anyerror!void { const page = try Page.from_ref(allocator, refname); defer page.deinit(); @@ -427,14 +441,14 @@ fn ref(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8) a // XXX: track ref count? } -fn ref_link(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8) anyerror!void { +fn ref_link(allocator: std.mem.Allocator, w: *std.Io.Writer, refname: []const u8) anyerror!void { const page = try Page.from_ref(allocator, refname); defer page.deinit(); try w.print("/{s}{s}", .{ page.html, page.anchor }); } -fn ref_name(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8) anyerror!void { +fn ref_name(allocator: std.mem.Allocator, w: *std.Io.Writer, refname: []const u8) anyerror!void { const page = try Page.from_ref(allocator, refname); defer page.deinit(); |