diff options
Diffstat (limited to 'scripts/kmd/src/main.zig')
-rw-r--r-- | scripts/kmd/src/main.zig | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/scripts/kmd/src/main.zig b/scripts/kmd/src/main.zig new file mode 100644 index 0000000..fdc033e --- /dev/null +++ b/scripts/kmd/src/main.zig @@ -0,0 +1,196 @@ +const std = @import("std"); +const kmd = @import("kmd.zig"); +const Allocator = std.mem.Allocator; + +// Work to do +// - Implement --io which takes an input and an output so +// save the need to spawn the program multiple times. + +// Globals +const stdout_file = std.io.getStdOut().writer(); +var bw = std.io.bufferedWriter(stdout_file); +const stdout = bw.writer(); + +var output: ?[]const u8 = null; +var input: ?[]const u8 = null; +var template: ?[]const u8 = null; +var debug = false; +var insert_br = false; +var show_hidden_comments = false; + +fn print(comptime fmt: []const u8, args: anytype) !void { + try stdout.print(fmt, args); + try bw.flush(); +} + +fn usage() noreturn { + print( + \\kmd: a set of utilities relating to the kmd format + \\`kmd convert-to-html`: + \\ -i INPUT The input Markdown file. + \\ Alternatively specify multiple with --io. + \\ -o OUTPUT The file to output to. Alternatively, + \\ specify multiple with --io. + \\ -t TEMPLATE The template to substitute into. $$CONTENTS$$, + \\ $$DATE$$, $$TITLE$$, $$WC$$, $$TTR$$ are substituted. + \\ -h Display this help message. + \\ kmd wc + \\ -w, -l, -b + \\ Retrieves the word, line, or byte count ignoring the header-seq. + \\ -t + \\ Allows passing multiple files, and the total is retrieved for these. + \\ -d + \\ Pass a directory and (non-recursively) get total count. Assumes all files in the directory are kmd. + \\ EXAMPLE kmd wc -wd $WEBSITE/blog + \\ kmd generate-index DIRECTORIES + \\ -s [title|date] [asc|dsc] + \\ Sort mode. + , .{}) catch { + std.process.exit(1); + }; + std.process.exit(0); +} + +pub fn convertToHtml(allocator: Allocator, args: anytype) !void { + var i: usize = 1; + while (i < args.len) : (i += 1) { + if (std.mem.eql(u8, args[i], "-o")) { + i += 1; + output = args[i]; + } else if (std.mem.eql(u8, args[i], "-i")) { + i += 1; + input = args[i]; + } else if (std.mem.eql(u8, args[i], "-t")) { + i += 1; + template = args[i]; + } else if (std.mem.eql(u8, args[i], "-d")) { + debug = true; + } else if (std.mem.eql(u8, args[i], "-h")) { + usage(); + } else if (std.mem.eql(u8, args[i], "-b")) { + insert_br = true; + } else if (std.mem.eql(u8, args[i], "-p")) { + show_hidden_comments = true; + } else { + std.debug.print("not a valid arg\n", .{}); + } + } + + if (input == null) { + std.debug.print("Did not pass input parameter -i\n", .{}); + std.process.exit(4); + } + const dir = std.fs.cwd(); + // const file = try std.fs.openFileAbsolute(input.?, .{}); + const file = try dir.openFile(input.?, .{}); + const bytes = try file.readToEndAlloc(allocator, std.math.maxInt(usize)); + defer allocator.free(bytes); + var md: kmd.Kmd = undefined; + md.init(bytes); + const html = try md.html(allocator, .{ + .br_after_newline = insert_br, + .show_hidden_comments = show_hidden_comments, + .debug = debug, + }, null); + defer allocator.free(html); + + if (template) |t| { + // read template + // const template_file = try std.fs.openFileAbsolute(t, .{}); + const template_file = try dir.openFile(t, .{}); + const template_bytes = try template_file.readToEndAlloc(allocator, std.math.maxInt(usize)); + defer allocator.free(template_bytes); + + // many allocations version + const r1 = try std.mem.replaceOwned(u8, allocator, template_bytes, "$$CONTENT$$", html); + const r2 = try std.mem.replaceOwned(u8, allocator, r1, "$$CONTENTS$$", html); + const r3 = try std.mem.replaceOwned(u8, allocator, r2, "$$DATE$$", md.date); + const r4 = try std.mem.replaceOwned(u8, allocator, r3, "$$TITLE$$", md.title); + const r5 = try std.mem.replaceOwned(u8, allocator, r4, "$$TAGS$$", if (std.mem.eql(u8, md.tags, "")) "none" else md.tags); + + const wc_ = md.wc(.words); + const wc_str = try std.fmt.allocPrint(allocator, "{}", .{wc_}); + defer allocator.free(wc_str); + const r6 = try std.mem.replaceOwned(u8, allocator, r5, "$$WC$$", wc_str); + + const ttr_str = try std.fmt.allocPrint(allocator, "{}", .{md.averageMinutesTakenToRead(wc_)}); + defer allocator.free(ttr_str); + const r7 = try std.mem.replaceOwned(u8, allocator, r6, "$$TTR$$", ttr_str); + + defer allocator.free(r1); + defer allocator.free(r2); + defer allocator.free(r3); + defer allocator.free(r4); + defer allocator.free(r5); + defer allocator.free(r6); + try print("{s}\n", .{r7}); + allocator.free(r7); + } else { + // output `html` to either stdout or a file + try print("{s}", .{html}); + } +} + +pub fn wc(allocator: Allocator, args: anytype) !void { + var mode: ?kmd.WcMode = null; + var file_str: ?[]const u8 = null; + var direc = false; + var total = false; + + var i: usize = 1; + while (i < args.len) : (i += 1) { + if (std.mem.eql(u8, args[i], "-h")) { + usage(); + } else if (args[i][0] == '-') { + // process flags + for (args[i][1..]) |f| switch (f) { + 'w' => mode = .words, + 'l' => mode = .lines, + 'b' => mode = .bytes, + 'd' => direc = true, + 't' => total = true, + else => { + std.debug.print("invalid flag {}\n", .{f}); + std.process.exit(5); + }, + }; + } else { + file_str = args[i]; + } + } + + if (file_str == null) { + std.debug.print("Did not pass file to run wc over\n", .{}); + std.process.exit(4); + } + + const dir = std.fs.cwd(); + const file = try dir.openFile(file_str.?, .{}); + const bytes = try file.readToEndAlloc(allocator, std.math.maxInt(usize)); + defer allocator.free(bytes); + var md: kmd.Kmd = undefined; + md.init(bytes); + try print("{any}\n", .{md.wc(mode orelse .words)}); + std.process.exit(0); +} + +pub fn main() !void { + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + const allocator = gpa.allocator(); + + const args = try std.process.argsAlloc(allocator); + + if (args.len <= 1) { + usage(); + } + + if (std.mem.eql(u8, args[1], "convert-to-html")) { + const rest_of_args = args[1..]; + try convertToHtml(allocator, rest_of_args); + } else if (std.mem.eql(u8, args[1], "wc")) { + const rest_of_args = args[1..]; + try wc(allocator, rest_of_args); + } else { + usage(); + } +} |