From 2200e168cfc35134aec2ccc656ad5419663a973c Mon Sep 17 00:00:00 2001 From: Robert Günzler Date: Wed, 8 Apr 2026 13:29:17 +0900 Subject: start refactoring to support multiple page roots MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Robert Günzler --- src/main.zig | 146 ++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 104 insertions(+), 42 deletions(-) (limited to 'src/main.zig') diff --git a/src/main.zig b/src/main.zig index 3edfb1c..fb8e687 100644 --- a/src/main.zig +++ b/src/main.zig @@ -7,6 +7,7 @@ const exe = @import("exe.zig"); const gen = @import("gen.zig"); +const fs = @import("fs.zig"); const std = @import("std"); @@ -14,20 +15,34 @@ const log = std.log.scoped(.rbc); // tune std.log options pub const std_options = std.Options{ - .log_level = .info, + .log_level = .debug, }; pub const Context = struct { + pub const Site = struct { + pub const Page = struct { + kind: enum { + Meta, + Htm, + Markdown, + }, + path: []const u8, + name: []const u8, + }; + + path: []const u8, + pages: std.ArrayListUnmanaged(Page) = .{}, + }; + arena: std.heap.ArenaAllocator, arena_mx: std.Thread.Mutex = .{}, alloc: std.heap.ThreadSafeAllocator = undefined, progress_nodes: std.ArrayListUnmanaged(std.Progress.Node) = .{}, progress_nodes_mx: std.Thread.Mutex = .{}, + progress_nodes_tl: ?*const std.Progress.Node = null, - pages: std.ArrayListUnmanaged([]const u8) = .{}, - markdown: std.ArrayListUnmanaged([]const u8) = .{}, - + sites: std.ArrayListUnmanaged(Site) = .{}, generated: std.ArrayListUnmanaged([]const u8) = .{}, meta: usize = 0, tilde: usize = 0, @@ -62,11 +77,6 @@ pub const Context = struct { .child_allocator = self.arena.allocator(), .mutex = self.arena_mx, }; - // create root progress node - try self.progress_nodes.append( - self.allocator(), - std.Progress.start(.{ .root_name = "" }), - ); return self; } @@ -82,17 +92,25 @@ pub const Context = struct { } // progress handling - pub fn progress_start(self: *Context, name: []const u8) void { + pub fn progress_start(self: *Context, name: []const u8, become_toplevel: bool) void { + const node = blk: { + if (self.progress_nodes_tl) |tl| + break :blk tl.start(name, 0); + + break :blk std.Progress.start(.{ .root_name = name }); + }; + + if (become_toplevel) self.progress_nodes_tl = &node; + self.progress_nodes_mx.lock(); - const new = self.progress_nodes.getLast().start(name, 0); - self.progress_nodes.append(self.allocator(), new) catch @panic("insufficient memory"); + self.progress_nodes.append(self.allocator(), node) catch @panic("insufficient memory"); self.progress_nodes_mx.unlock(); } pub fn progress_end(self: *Context) void { self.progress_nodes_mx.lock(); - const current = self.progress_nodes.pop() orelse return; + const node = self.progress_nodes.pop() orelse return; self.progress_nodes_mx.unlock(); - current.end(); + node.end(); } }; @@ -102,14 +120,14 @@ pub const Context = struct { // fn index(ctx: *Context) !void { // avoid reindexing - if ((ctx.pages.items.len != 0) and (ctx.markdown.items.len != 0)) return; + if (ctx.sites.items.len != 0) return; - ctx.progress_start("index"); + ctx.progress_start("index", true); defer ctx.progress_end(); var root = std.fs.cwd().openDir(Context.params.PAGE_PATH, .{ .iterate = true }) catch |err| switch (err) { error.FileNotFound => { - std.log.err("Missing {s} folder.", .{Context.params.PAGE_PATH}); + log.err("Missing {s} folder.", .{Context.params.PAGE_PATH}); std.os.linux.exit(1); }, else => |e| return e, @@ -119,19 +137,45 @@ fn index(ctx: *Context) !void { var walk = try root.walk(ctx.allocator()); defer walk.deinit(); + var meta: u32 = 0; + var htm: u32 = 0; + var md: u32 = 0; + + // root site + log.debug("Indexing site root", .{}); + var site = Context.Site{ .path = "." }; + while (try walk.next()) |e| { switch (e.kind) { .file => { - ctx.progress_start(e.basename); + ctx.progress_start(e.basename, false); defer ctx.progress_end(); - if (std.mem.endsWith(u8, e.basename, ".htm")) { - std.log.debug("Indexing {s}", .{e.path}); - try ctx.pages.append(ctx.allocator(), try ctx.allocator().dupe(u8, e.path)); - } - if (std.mem.endsWith(u8, e.basename, ".md")) { - std.log.debug("Indexing {s}", .{e.path}); - try ctx.markdown.append(ctx.allocator(), try ctx.allocator().dupe(u8, e.path)); + if (std.mem.startsWith(u8, e.basename, "meta.")) { + log.debug("Indexing meta {s}", .{e.path}); + try site.pages.append(ctx.allocator(), .{ + .kind = .Meta, + .name = try ctx.allocator().dupe(u8, try fs.stripExtension(e.basename)), + .path = try ctx.allocator().dupe(u8, e.path), + }); + meta += 1; + } else if (std.mem.endsWith(u8, e.basename, ".htm")) { + log.debug("--> {s}", .{std.mem.trimEnd(u8, e.basename, ".htm")}); + log.debug("Indexing page {s}", .{e.path}); + try site.pages.append(ctx.allocator(), .{ + .kind = .Htm, + .name = try ctx.allocator().dupe(u8, try fs.stripExtension(e.basename)), + .path = try ctx.allocator().dupe(u8, e.path), + }); + htm += 1; + } else if (std.mem.endsWith(u8, e.basename, ".md")) { + log.debug("Indexing page {s}", .{e.path}); + try site.pages.append(ctx.allocator(), .{ + .kind = .Markdown, + .name = try ctx.allocator().dupe(u8, try fs.stripExtension(e.basename)), + .path = try ctx.allocator().dupe(u8, e.path), + }); + md += 1; } // XXX: scan for refs here? @@ -140,8 +184,26 @@ fn index(ctx: *Context) !void { } } - log.info("Indexed {d} pages.", .{ctx.pages.items.len}); - log.info("Indexed {d} markdown files.", .{ctx.markdown.items.len}); + try ctx.sites.append(ctx.allocator(), site); + + // sort pages by name + for (ctx.sites.items) |s| { + std.mem.sort( + Context.Site.Page, + s.pages.items, + {}, + struct { + fn lessthan(_: void, a: Context.Site.Page, b: Context.Site.Page) bool { + return std.ascii.lessThanIgnoreCase(a.name, b.name); + } + }.lessthan, + ); + } + + log.info("Indexed {d} sites.", .{ctx.sites.items.len}); + log.info("Indexed {d} meta pages.", .{meta}); + log.info("Indexed {d} htm pages.", .{htm}); + log.info("Indexed {d} markdown pages.", .{md}); return; } @@ -206,11 +268,11 @@ const Cli = struct { } fn mdCmd(ctx: *Context, argv: ?*std.process.ArgIterator) !void { - try index(ctx); - try exe.runPandoc(ctx); + try index(ctx); + try exe.runPandoc(ctx); - if (checkOpts(argv, &.{ "-c", "--commit" })) - try exe.commit(ctx, ctx.generated.items); + if (checkOpts(argv, &.{ "-c", "--commit" })) + try exe.commit(ctx, ctx.generated.items); } fn watchCmd(ctx: *Context) !void { @@ -223,19 +285,19 @@ const Cli = struct { } fn serveCmd(ctx: *Context) !void { - try exe.shell(ctx, - \\python -m http.server 1414 - , null); + // try exe.shell(ctx, + // \\python -m http.server 1414 + // , null); - // var env_map = try std.process.getEnvMap(ctx.allocator()); - // defer env_map.deinit(); + var env_map = try std.process.getEnvMap(ctx.allocator()); + defer env_map.deinit(); - // try env_map.put("CADDY_HTTP_PORT", "1414"); - // try env_map.put("CADDY_HOST", "localhost"); - // - // try exe.shell(ctx, - // \\caddy fmt --overwrite && caddy run --watch - // , &env_map); + try env_map.put("CADDY_HTTP_PORT", "1414"); + try env_map.put("CADDY_HOST", "localhost"); + + try exe.shell(ctx, + \\caddy fmt --overwrite && caddy run --watch + , &env_map); } }; -- cgit 1.4.1