diff options
Diffstat (limited to 'src/gen.zig')
| -rw-r--r-- | src/gen.zig | 134 |
1 files changed, 29 insertions, 105 deletions
diff --git a/src/gen.zig b/src/gen.zig index 721b08a..3ea0bc2 100644 --- a/src/gen.zig +++ b/src/gen.zig @@ -1,12 +1,13 @@ const std = @import("std"); -const c = @cImport({ - @cInclude("time.h"); -}); const log = std.log.scoped(.gen); const Context = @import("main.zig").Context; +const fs = @import("fs.zig"); pub fn generate(ctx: *Context) !void { + ctx.progress_start("generate"); + defer ctx.progress_end(); + try genIndexHtml(ctx); log.info("Generated index.", .{}); @@ -18,10 +19,13 @@ pub fn generate(ctx: *Context) !void { } fn genIndexHtml(ctx: *Context) !void { - const srcpathIndex = try util.joinIn(ctx.allocator(), &.{Context.params.PAGE_PATH}, &.{"index.htm"}); + ctx.progress_start("index.html"); + defer ctx.progress_end(); + + const srcpathIndex = try fs.join_path_and_filename(ctx.allocator(), &.{Context.params.PAGE_PATH}, &.{"index.htm"}); defer ctx.allocator().free(srcpathIndex); - const f = try FileSwapper.createAt(ctx.allocator(), srcpathIndex); + const f = try fs.FileSwapper.createAt(ctx.allocator(), srcpathIndex); defer f.close(); try f.writer().writeAll( @@ -32,7 +36,7 @@ fn genIndexHtml(ctx: *Context) !void { // alphanum ascii sort std.mem.sort( []const u8, - ctx.pages, + ctx.pages.items, {}, struct { fn lessthan(_: void, a: []const u8, b: []const u8) bool { @@ -41,11 +45,11 @@ fn genIndexHtml(ctx: *Context) !void { }.lessthan, ); - for (ctx.pages) |p| { + for (ctx.pages.items) |p| { if (std.mem.startsWith(u8, p, "meta.")) continue; - const dstname = try util.stripExt(p); - const dstpath = try util.joinIn(ctx.allocator(), &.{Context.params.SITE_PATH}, &.{ dstname, ".html" }); + const dstname = try fs.strip_extension(p); + const dstpath = try fs.join_path_and_filename(ctx.allocator(), &.{Context.params.SITE_PATH}, &.{ dstname, ".html" }); defer ctx.allocator().free(dstpath); try f.writer().print( @@ -63,58 +67,22 @@ fn genIndexHtml(ctx: *Context) !void { ); } -const FileSwapper = struct { - allocator: std.mem.Allocator, - target_path: []const u8, - tmp_path: []const u8, - tmp: std.fs.File, - - fn createAt(allocator: std.mem.Allocator, path: []const u8) !FileSwapper { - const target_dir = std.fs.path.dirname(path) orelse "."; - const target_name = std.fs.path.basename(path); - - const tmp_name = try std.fmt.allocPrint(allocator, ".{s}", .{target_name}); - defer allocator.free(tmp_name); - - const tmp_path = try std.fs.path.join(allocator, &.{ target_dir, tmp_name }); - - const f = try std.fs.cwd().createFile(tmp_path, .{}); - - return .{ - .allocator = allocator, - .target_path = path, - .tmp_path = tmp_path, - .tmp = f, - }; - } - - fn writer(self: FileSwapper) std.fs.File.Writer { - return self.tmp.writer(); - } - - fn close(self: FileSwapper) void { - defer self.allocator.free(self.tmp_path); - defer self.tmp.close(); - - self.tmp.sync() catch @panic("sync tmp file"); - - std.debug.print("??? {s} => {s}\n", .{ self.tmp_path, self.target_path }); - std.fs.rename(std.fs.cwd(), self.tmp_path, std.fs.cwd(), self.target_path) catch @panic("rename tmp file"); - } -}; - fn genSite(ctx: *Context) !void { - for (ctx.pages) |p| { + for (ctx.pages.items) |p| { const pname = std.fs.path.basename(p); + + ctx.progress_start(pname); + defer ctx.progress_end(); + if (std.mem.startsWith(u8, pname, "meta.")) { try meta(ctx, p); continue; } - const dstname = try util.stripExt(p); - const srcpath = try util.joinIn(ctx.allocator(), &.{Context.params.PAGE_PATH}, &.{ dstname, ".htm" }); + const dstname = try fs.strip_extension(p); + const srcpath = try fs.join_path_and_filename(ctx.allocator(), &.{Context.params.PAGE_PATH}, &.{ dstname, ".htm" }); defer ctx.allocator().free(srcpath); - const dstpath = try util.joinIn(ctx.allocator(), &.{Context.params.SITE_PATH}, &.{ dstname, ".html" }); + const dstpath = try fs.join_path_and_filename(ctx.allocator(), &.{Context.params.SITE_PATH}, &.{ dstname, ".html" }); defer ctx.allocator().free(dstpath); const rel_dstpath = try std.fs.path.relative(ctx.allocator(), Context.params.SITE_PATH, dstpath); defer ctx.allocator().free(rel_dstpath); @@ -122,7 +90,7 @@ fn genSite(ctx: *Context) !void { log.debug("generating {s} at {s}", .{ p, rel_dstpath }); if (std.fs.path.dirname(rel_dstpath)) |d| { - const dstdir = try util.joinIn(ctx.allocator(), &.{Context.params.SITE_PATH}, &.{d}); + const dstdir = try fs.join_path_and_filename(ctx.allocator(), &.{Context.params.SITE_PATH}, &.{d}); defer ctx.allocator().free(dstdir); try std.fs.cwd().makePath(dstdir); @@ -140,7 +108,7 @@ fn genSite(ctx: *Context) !void { // build a single html file fn build(allocator: std.mem.Allocator, f: std.fs.File, page_name: []const u8, srcpath: []const u8) !void { - const mtime = try util.getMtime(allocator, srcpath); + const mtime = try fs.get_mtime(allocator, srcpath); defer allocator.free(mtime); // HEAD @@ -238,9 +206,9 @@ fn meta(ctx: *Context, p: []const u8) !void { if (std.mem.startsWith(u8, p, "meta.tilde.")) { const dot = std.mem.indexOfPosLinear(u8, p, 11, "."); const dstname = p[11..dot.?]; - const srcpath = try util.joinIn(ctx.allocator(), &.{Context.params.PAGE_PATH}, &.{p}); + const srcpath = try fs.join_path_and_filename(ctx.allocator(), &.{Context.params.PAGE_PATH}, &.{p}); defer ctx.allocator().free(srcpath); - const dstpath = try util.joinIn(ctx.allocator(), &.{Context.params.LINK_PATH}, &.{ "~", dstname }); + const dstpath = try fs.join_path_and_filename(ctx.allocator(), &.{Context.params.LINK_PATH}, &.{ "~", dstname }); defer ctx.allocator().free(dstpath); const link = blk: { @@ -346,9 +314,9 @@ fn template(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const fn portal(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8, insert_heading: bool) anyerror!void { const basename = try std.mem.replaceOwned(u8, allocator, refname, " ", "_"); defer allocator.free(basename); - const refpathPage = try util.joinIn(allocator, &.{Context.params.PAGE_PATH}, &.{ basename, ".htm" }); + const refpathPage = try fs.join_path_and_filename(allocator, &.{Context.params.PAGE_PATH}, &.{ basename, ".htm" }); defer allocator.free(refpathPage); - const refpathSite = try util.joinIn(allocator, &.{Context.params.SITE_PATH}, &.{ basename, ".html" }); + const refpathSite = try fs.join_path_and_filename(allocator, &.{Context.params.SITE_PATH}, &.{ basename, ".html" }); defer allocator.free(refpathSite); if (insert_heading) @@ -369,7 +337,7 @@ fn portal(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8 fn ref(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8) anyerror!void { const basename = try std.mem.replaceOwned(u8, allocator, refname, " ", "_"); defer allocator.free(basename); - const refpathSite = try util.joinIn(allocator, &.{Context.params.SITE_PATH}, &.{ basename, ".html" }); + const refpathSite = try fs.join_path_and_filename(allocator, &.{Context.params.SITE_PATH}, &.{ basename, ".html" }); defer allocator.free(refpathSite); try w.print( @@ -385,7 +353,7 @@ fn ref(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8) a fn ref_link(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8) anyerror!void { const basename = try std.mem.replaceOwned(u8, allocator, refname, " ", "_"); defer allocator.free(basename); - const refpathSite = try util.joinIn(allocator, &.{Context.params.SITE_PATH}, &.{ basename, ".html" }); + const refpathSite = try fs.join_path_and_filename(allocator, &.{Context.params.SITE_PATH}, &.{ basename, ".html" }); defer allocator.free(refpathSite); try w.print("/{s}", .{refpathSite}); @@ -394,47 +362,3 @@ fn ref_link(allocator: std.mem.Allocator, w: std.io.AnyWriter, refname: []const fn ref_name(_: std.mem.Allocator, w: std.io.AnyWriter, refname: []const u8) anyerror!void { try w.print("{s}", .{refname}); } - -const util = struct { - // also trims off base paths - fn stripExt(path: []const u8) ![]const u8 { - const ext = std.fs.path.extension(path); - const ext_idx = std.mem.indexOfPosLinear(u8, path, 0, ext); - std.debug.assert(ext_idx != null); - return path[0..ext_idx.?]; - } - - fn joinIn(allocator: std.mem.Allocator, paths: []const []const u8, filename_parts: []const []const u8) ![]u8 { - const filename = try std.mem.concat(allocator, u8, filename_parts); - defer allocator.free(filename); - - var p = try std.ArrayList([]const u8).initCapacity(allocator, paths.len + 1); - defer p.deinit(); - - p.appendSliceAssumeCapacity(paths); - p.appendAssumeCapacity(filename); - - const paths2 = try p.toOwnedSlice(); - defer allocator.free(paths2); - - std.debug.assert(paths.len + 1 == paths2.len); - return try std.fs.path.join(allocator, paths2); - } - - fn getMtime(allocator: std.mem.Allocator, srcpath: []const u8) ![]u8 { - const attr = try allocator.create(std.os.linux.Stat); - defer allocator.destroy(attr); - const srcpathZ = try allocator.dupeZ(u8, srcpath); - defer allocator.free(srcpathZ); - _ = std.os.linux.stat(srcpathZ, attr); - const mtime = attr.mtime(); - const mtime_str = try allocator.alloc(u8, 512); - const n = c.strftime( - mtime_str.ptr, - mtime_str.len, - "%F", - c.localtime(&mtime.sec), - ); - return try allocator.realloc(mtime_str, n); - } -}; |