~clarity/sitegen

21fb839b8bc1c6426bd059b7a0be995cff93aae1 — Clarity Flowers 11 months ago 237d1d2 root
Update to zig 0.9.1
2 files changed, 41 insertions(+), 44 deletions(-)

M pkg/args
M src/main.zig
M pkg/args => pkg/args +1 -1
@@ 1,1 1,1 @@
Subproject commit ecc8861c9f60f1325390cf03e8261a06fdf1eabb
Subproject commit d85b9756f1cc5fd05f1a47c85080a0843d82adb4

M src/main.zig => src/main.zig +40 -43
@@ 36,15 36,14 @@ pub fn log(
    args: anytype,
) void {
    _ = scope;
    const held = std.debug.getStderrMutex().acquire();
    defer held.release();
    std.debug.getStderrMutex().lock();
    defer std.debug.getStderrMutex().unlock();
    const stderr = std.io.getStdErr().writer();
    const color: []const u8 = switch (message_level) {
        .emerg, .alert, .crit, .err => "\x1B[1;91m", // red
        .err => "\x1B[1;91m", // red
        .warn => "\x1B[1;93m", // yellow
        .debug => "\x1B[36m", // blue
        .info => "\x1B[37m", // gray
        else => "",
    };
    const reset = if (color.len > 0) "\x1B[0m" else "";
    nosuspend stderr.print(color ++ format ++ "\n" ++ reset, args) catch return;


@@ 63,7 62,7 @@ const SitegenArgs = Args.Result(sitegen_args);
pub fn main() u8 {
    mainWrapped() catch |err| {
        if (builtin.mode == .Debug) {
            std.debug.warn("{}{s}\n", .{ @errorReturnTrace(), @errorName(err) });
            std.debug.print("{}{s}\n", .{ @errorReturnTrace(), @errorName(err) });
        } else return @intCast(u8, @errorToInt(err)) + 1;
    };
    return 0;


@@ 74,17 73,17 @@ fn mainWrapped() anyerror!void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer if (gpa.deinit()) logger.debug("Detected memory leak.", .{});

    env_map = try std.process.getEnvMap(&gpa.allocator);
    env_map = try std.process.getEnvMap(gpa.allocator());
    defer env_map.deinit();

    var args_arena = std.heap.ArenaAllocator.init(&gpa.allocator);
    var args_arena = std.heap.ArenaAllocator.init(gpa.allocator());
    defer args_arena.deinit();
    const args_list = try std.process.argsAlloc(&args_arena.allocator);
    const args_list = try std.process.argsAlloc(args_arena.allocator());

    if (try sitegen_args.parse(args_list[1..])) |command| {
        switch (command) {
            .make => |args| try make(args, &gpa.allocator),
            .index => |args| try buildIndex(args, &gpa.allocator),
            .make => |args| try make(args, gpa.allocator()),
            .index => |args| try buildIndex(args, gpa.allocator()),
            .docs => try std.io.getStdOut().writeAll(@embedFile("docs.txt")),
            .html_template => try std.io.getStdOut().writeAll(@embedFile("default_template.html")),
            .gmi_template => try std.io.getStdOut().writeAll(@embedFile("default_template.gmi")),


@@ 115,7 114,7 @@ const MakeArgs = Args.Result(make_args);
/// Generate the site for all targets
fn make(
    args: MakeArgs,
    allocator: *std.mem.Allocator,
    allocator: std.mem.Allocator,
) !void {
    var cwd = std.fs.cwd();



@@ 142,8 141,8 @@ fn make(
        try env_map.put("PATH", new_path);
    }

    const html_template = try Template.get(&cwd, &arena.allocator, args.html, .html);
    const gmi_template = try Template.get(&cwd, &arena.allocator, args.gmi, .gmi);
    const html_template = try Template.get(&cwd, arena.allocator(), args.html, .html);
    const gmi_template = try Template.get(&cwd, arena.allocator(), args.gmi, .gmi);

    try cwd.makePath(args.out_dir);
    var out_dir = try cwd.openDir(args.out_dir, .{});


@@ 177,7 176,7 @@ fn make(
pub const RenderOptions = struct {
    html_template: *const Template,
    gmi_template: *const Template,
    allocator: *std.mem.Allocator,
    allocator: std.mem.Allocator,
};
pub const RenderTargets = struct {
    dirname: ?[]const u8,


@@ 262,12 261,12 @@ fn renderFile(
    const src_file = try targets.src.openFile(filename, .{});
    defer src_file.close();
    const lines = blk: {
        var lines_list = std.ArrayList([]const u8).init(&arena.allocator);
        var lines_list = std.ArrayList([]const u8).init(arena.allocator());
        try readLines(src_file.reader(), &lines_list);
        break :blk lines_list.toOwnedSlice();
    };

    const doc = (try parseDocument(lines, &arena.allocator, file_info)) orelse return;
    const doc = (try parseDocument(lines, arena.allocator(), file_info)) orelse return;
    const stdout = std.io.getStdOut().writer();
    if (!silent) {
        if (targets.dirname) |dirname| {


@@ 281,11 280,11 @@ fn renderFile(
        const dir = @field(targets, field.name);
        const template = @field(options, field.name ++ "_template");
        const out_filename = try std.mem.concat(
            &arena.allocator,
            arena.allocator(),
            u8,
            &[_][]const u8{ filename_no_ext, "." ++ field.name },
        );
        defer arena.allocator.free(out_filename);
        defer arena.allocator().free(out_filename);
        const out_file = try dir.createFile(
            out_filename,
            .{ .truncate = true },


@@ 323,7 322,7 @@ const FileInfo = struct { name: []const u8, dir: ?[]const u8, parent_title: ?[]c
const ParseContext = struct {
    info: Info,
    file: FileInfo,
    allocator: *std.mem.Allocator,
    allocator: std.mem.Allocator,
};

const Change = struct { date: Date, what_changed: ?[]const u8 = null };


@@ 384,7 383,7 @@ const Anchor = struct { url: []const u8, text: []const Span };
/// mistype something it'll usually just fall back to raw text.
fn parseDocument(
    lines: []const []const u8,
    allocator: *std.mem.Allocator,
    allocator: std.mem.Allocator,
    file: FileInfo,
) !?Document {
    const info_res = try parseInfo(lines, file.name, allocator);


@@ 432,10 431,10 @@ fn ok(data: anytype, new_pos: usize) ParseResult(@TypeOf(data)) {
fn parseInfo(
    lines: []const []const u8,
    filename: []const u8,
    allocator: *std.mem.Allocator,
    allocator: std.mem.Allocator,
) ParseInfoError!ParseResult(Info) {
    if (lines.len == 0) {
        logger.alert("File {s} has no info", .{filename});
        logger.err("File {s} has no info", .{filename});
        return error.NoInfo;
    }
    const title = lines[0];


@@ 467,14 466,14 @@ fn parseInfo(
        } else if (parseLiteral(lines[line], 0, "Using ")) |index| {
            shell = lines[line][index..];
        } else {
            logger.alert("\"{s}\" (at {s}) has unexpected info \"{s}\" on line {d}.", .{ title, filename, lines[line], line + 1 });
            logger.err("\"{s}\" (at {s}) has unexpected info \"{s}\" on line {d}.", .{ title, filename, lines[line], line + 1 });
            return error.UnexpectedInfo;
        }
    }
    return ok(Info{
        .title = title,
        .created = created orelse {
            logger.alert("\"{s}\" (at {s}) has no written date", .{ title, filename });
            logger.err("\"{s}\" (at {s}) has no written date", .{ title, filename });
            return error.NoCreatedDate;
        },
        .changes = changes.toOwnedSlice(),


@@ 522,7 521,7 @@ fn parseBlocks(
fn parseBlock(
    lines: []const []const u8,
    line: usize,
    allocator: *std.mem.Allocator,
    allocator: std.mem.Allocator,
) !?ParseResult(Block) {
    if (lines[line].len == 0) {
        return ok(Block{ .empty = {} }, line + 1);


@@ 545,7 544,7 @@ fn parseBlock(
    } else return null;
}

fn parseRaw(lines: []const []const u8, start: usize, allocator: *std.mem.Allocator) !?ParseResult(Raw) {
fn parseRaw(lines: []const []const u8, start: usize, allocator: std.mem.Allocator) !?ParseResult(Raw) {
    inline for (@typeInfo(Ext).Enum.fields) |fld| {
        if (try parsePrefixedLines(lines, start, "." ++ fld.name, allocator)) |res| {
            return ok(


@@ 561,7 560,7 @@ fn parsePrefixedLines(
    lines: []const []const u8,
    start: usize,
    comptime prefix: []const u8,
    allocator: *std.mem.Allocator,
    allocator: std.mem.Allocator,
) !?ParseResult([]const []const u8) {
    if (!std.mem.startsWith(u8, lines[start], prefix ++ " ")) return null;
    var line = start;


@@ 587,7 586,7 @@ fn parseSubheading(line: []const u8) ?[]const u8 {
fn parseList(
    lines: []const []const u8,
    start: usize,
    allocator: *std.mem.Allocator,
    allocator: std.mem.Allocator,
    comptime symbol: []const u8,
) ParseError!?ParseResult([]const []const Span) {
    var ll = start;


@@ 662,7 661,7 @@ fn parseWrapper(
    lines: []const []const u8,
    start: usize,
    comptime prefix: []const u8,
    allocator: *std.mem.Allocator,
    allocator: std.mem.Allocator,
) !?ParseResult([]const []const Span) {
    if (!std.mem.startsWith(u8, lines[start], prefix)) return null;
    var line = start;


@@ 703,7 702,7 @@ fn parseSpans(
    start: usize,
    comptime open: ?[]const u8,
    comptime close: ?[]const u8,
    allocator: *std.mem.Allocator,
    allocator: std.mem.Allocator,
) ParseError!?ParseResult([]const Span) {
    var col = start;
    if (open) |match| {


@@ 740,7 739,7 @@ fn parseSpans(
fn parseSpan(
    line: []const u8,
    start: usize,
    allocator: *std.mem.Allocator,
    allocator: std.mem.Allocator,
) ParseError!?ParseResult(Span) {
    if (try parseSpans(line, start, "_", "_", allocator)) |result| {
        return ok(Span{ .emphasis = result.data }, result.new_pos);


@@ 754,7 753,7 @@ fn parseSpan(
fn parseAnchor(
    line: []const u8,
    start: usize,
    allocator: *std.mem.Allocator,
    allocator: std.mem.Allocator,
) ParseError!?ParseResult(Anchor) {
    if (try parseSpans(line, start, "[", "](", allocator)) |res| {
        const end_index = std.mem.indexOfPos(


@@ 1048,7 1047,7 @@ const IndexArgs = Args.Result(index_args);
/// building directories or feeds.
fn buildIndex(
    args: IndexArgs,
    allocator: *std.mem.Allocator,
    allocator: std.mem.Allocator,
) !void {
    var arena = std.heap.ArenaAllocator.init(allocator);
    defer arena.deinit();


@@ 1058,13 1057,13 @@ fn buildIndex(
        include_private = true;
    }
    const limit = if (args.limit) |limit| std.fmt.parseInt(usize, limit, 10) catch {
        logger.alert("Limit value must be positive integer, got: {s}", .{
        logger.err("Limit value must be positive integer, got: {s}", .{
            limit,
        });
        return error.BadArgs;
    } else null;
    const cwd = std.fs.cwd();
    var pages = std.ArrayList(IndexEntry).init(&arena.allocator);
    var pages = std.ArrayList(IndexEntry).init(arena.allocator());
    for (args.file) |filename| {
        if (!std.mem.endsWith(u8, filename, ".txt")) continue;



@@ 1073,9 1072,9 @@ fn buildIndex(

        const lines = blk: {
            var lines = std.ArrayList([]const u8).init(
                &arena.allocator,
                arena.allocator(),
            );
            var line = std.ArrayList(u8).init(&arena.allocator);
            var line = std.ArrayList(u8).init(arena.allocator());
            while (try readLine(file.reader(), &line)) {
                if (line.items.len == 0) break;
                try lines.append(line.toOwnedSlice());


@@ 1186,7 1185,7 @@ const Template = struct {
    }

    // Caller must call deinit() on result
    fn parse(text: []const u8, allocator: *std.mem.Allocator) !Template {
    fn parse(text: []const u8, allocator: std.mem.Allocator) !Template {
        var header_tokens = Tokens{};
        errdefer header_tokens.deinit(allocator);
        var footer_tokens = Tokens{};


@@ 1252,7 1251,7 @@ const Template = struct {
            .text = text,
        };
    }
    fn get(cwd: *std.fs.Dir, allocator: *std.mem.Allocator, template_file: ?[]const u8, comptime ext: Ext) !Template {
    fn get(cwd: *std.fs.Dir, allocator: std.mem.Allocator, template_file: ?[]const u8, comptime ext: Ext) !Template {
        return try parse(
            if (template_file) |file|
                try cwd.readFileAlloc(


@@ 1394,7 1393,7 @@ fn readLines(
/// content. Not very much code and A LOT of power.
fn expand(
    original_lines: []const []const u8,
    allocator: *std.mem.Allocator,
    allocator: std.mem.Allocator,
    custom_shell: ?[]const u8,
    filename: []const u8,
) ![]const []const u8 {


@@ 1437,9 1436,7 @@ fn expand(
                    logger.warn("Had trouble cleaning up process: {}", .{err});
                };
                const writer = process.stdin.?.writer();
                logger.info("Running command:", .{});
                for (lines[start..i]) |line| {
                    logger.info("{s}", .{line});
                    try writer.print("{s}\n", .{line[2..]});
                }
                process.stdin.?.close();


@@ 1450,7 1447,7 @@ fn expand(
                switch (try process.wait()) {
                    .Exited => |status| {
                        if (status != 0) {
                            logger.alert("Process ended unexpectedly", .{});
                            logger.err("Process ended unexpectedly", .{});
                            return error.ProcessEndedUnexpectedly;
                        }
                    },