From 276100c55692c6f65f4f87efbadd3cfb63b410a3 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 8 Jul 2019 15:40:31 -0300 Subject: [PATCH] add implementation for quicksave command --- src/runner.zig | 66 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/src/runner.zig b/src/runner.zig index 797e249..90ccd08 100644 --- a/src/runner.zig +++ b/src/runner.zig @@ -7,6 +7,7 @@ const Image = images.Image; pub const RunError = error{ UnknownCommand, NoBMP, + ImageRequired, }; pub const Runner = struct { @@ -72,6 +73,68 @@ pub const Runner = struct { self.image = try Image.open(self.allocator, load_path); } + fn getImage(self: *Runner) !*Image { + if (self.image) |image| { + return image; + } else { + std.debug.warn("image is required!\n"); + return RunError.ImageRequired; + } + } + + fn quicksaveCmd(self: *Runner) !void { + // we want to transform basename, if it is "x.bmp" to "x_gN.bmp", where + // N is the maximum non-used integer. + var image = try self.getImage(); + + const basename = std.fs.path.basename(image.path); + const dirname = std.fs.path.dirname(image.path).?; + + var dir = try std.fs.Dir.open(self.allocator, dirname); + defer dir.close(); + + const period_idx = std.mem.lastIndexOf(u8, basename, ".").?; + const extension = basename[period_idx..basename.len]; + + // starts_with would be "x_g", we want to find all files in the directory + // that start with that name. + const starts_with = try std.fmt.allocPrint( + self.allocator, + "{}_g", + basename[0..period_idx], + ); + + var max: usize = 0; + + while (try dir.next()) |entry| { + switch (entry.kind) { + .File => blk: { + if (!std.mem.startsWith(u8, entry.name, starts_with)) break :blk {}; + + // we want to get the N in x_gN.ext + const entry_gidx = std.mem.lastIndexOf(u8, entry.name, "_g").?; + + const entry_pidx_opt = std.mem.lastIndexOf(u8, entry.name, "."); + if (entry_pidx_opt == null) break :blk {}; + + const entry_pidx = entry_pidx_opt.?; + + // if N isn't a number, we just ignore that file + const idx_str = entry.name[entry_gidx + 2 .. entry_pidx]; + const idx = std.fmt.parseInt(usize, idx_str, 10) catch |err| { + break :blk {}; + }; + + if (idx > max) max = idx; + }, + else => {}, + } + } + + const out_path = try std.fmt.allocPrint(self.allocator, "{}_g{}{}", starts_with, max + 1, extension); + std.debug.warn("out path: {}\n", out_path); + } + fn runCommand(self: *Runner, cmd: *lang.Command) !void { return switch (cmd.command) { .Noop => {}, @@ -81,8 +144,7 @@ pub const Runner = struct { break :blk; }, - .Quicksave => {}, - //.Quicksave => try self.quicksaveCmd(), + .Quicksave => try self.quicksaveCmd(), else => blk: { std.debug.warn("Unknown command: {}\n", cmd.command); break :blk RunError.UnknownCommand;