feat: improve CLI and take confgen file as CLI argument
This commit is contained in:
parent
459834e134
commit
8ebdb27fbf
34
build.zig
34
build.zig
|
@ -1,29 +1,27 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.build.Builder) void {
|
||||
// Standard target options allows the person running `zig build` to choose
|
||||
// what target to build for. Here we do not override the defaults, which
|
||||
// means any target is allowed, and the default is native. Other options
|
||||
// for restricting supported target set are available.
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
// Standard release options allow the person running `zig build` to select
|
||||
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
|
||||
const mode = b.standardOptimizeOption(.{});
|
||||
const zig_args = b.dependency("zig_args", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
}).module("args");
|
||||
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "confgen",
|
||||
.root_source_file = .{ .path = "src/main.zig" },
|
||||
.target = target,
|
||||
.optimize = mode,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
exe.strip = mode != .Debug and mode != .ReleaseSafe;
|
||||
setupExe(exe);
|
||||
exe.strip = optimize != .Debug and optimize != .ReleaseSafe;
|
||||
setupExe(exe, zig_args);
|
||||
|
||||
exe.install();
|
||||
b.installArtifact(exe);
|
||||
|
||||
const run_cmd = exe.run();
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
if (b.args) |args| {
|
||||
run_cmd.addArgs(args);
|
||||
|
@ -35,17 +33,19 @@ pub fn build(b: *std.build.Builder) void {
|
|||
const exe_tests = b.addTest(.{
|
||||
.root_source_file = .{ .path = "src/main.zig" },
|
||||
.target = target,
|
||||
.optimize = mode,
|
||||
.optimize = optimize,
|
||||
});
|
||||
setupExe(exe_tests);
|
||||
setupExe(exe_tests, zig_args);
|
||||
|
||||
const test_step = b.step("test", "Run unit tests");
|
||||
test_step.dependOn(&exe_tests.step);
|
||||
test_step.dependOn(&b.addRunArtifact(exe_tests).step);
|
||||
}
|
||||
|
||||
fn setupExe(exe: *std.build.LibExeObjStep) void {
|
||||
fn setupExe(exe: *std.Build.CompileStep, zig_args: *std.Build.Module) void {
|
||||
exe.linkLibC();
|
||||
exe.linkSystemLibrary("luajit");
|
||||
|
||||
exe.addModule("args", zig_args);
|
||||
|
||||
exe.unwind_tables = true;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
.{
|
||||
.name = "confgen",
|
||||
.version = "0.0.0",
|
||||
|
||||
.dependencies = .{
|
||||
.zig_args = .{
|
||||
.url = "https://mzte.de/git/mirrors/zig-args/archive/cce1b8987723c155d1fa61c4e6cac717074a2e74.tar.gz",
|
||||
.hash = "122087f17682383feb354fecb2505788fdced06639f34e750cf641909fc6dcd76801",
|
||||
},
|
||||
},
|
||||
}
|
|
@ -48,6 +48,23 @@ pub fn initLuaState(cgstate: *CgState) !*c.lua_State {
|
|||
// open all lua libs
|
||||
c.luaL_openlibs(l);
|
||||
|
||||
// Add root path to package.path
|
||||
c.lua_getglobal(l, "_G");
|
||||
c.lua_getfield(l, -1, "package");
|
||||
|
||||
const root_luapath_prefix = try std.fmt.allocPrintZ(
|
||||
std.heap.c_allocator,
|
||||
"{s}/?.lua;",
|
||||
.{cgstate.rootpath},
|
||||
);
|
||||
defer std.heap.c_allocator.free(root_luapath_prefix);
|
||||
|
||||
c.lua_pushlstring(l, root_luapath_prefix.ptr, root_luapath_prefix.len);
|
||||
c.lua_getfield(l, -2, "path");
|
||||
c.lua_concat(l, 2);
|
||||
c.lua_setfield(l, -2, "path");
|
||||
c.lua_pop(l, 2);
|
||||
|
||||
// create opt table
|
||||
c.lua_newtable(l);
|
||||
|
||||
|
@ -143,7 +160,10 @@ fn lAddPath(l: *c.lua_State) !c_int {
|
|||
|
||||
const state = getState(l);
|
||||
|
||||
var dir = try std.fs.cwd().openIterableDir(path, .{});
|
||||
const resolved_path = try std.fs.path.join(std.heap.c_allocator, &.{ state.rootpath, path });
|
||||
defer std.heap.c_allocator.free(resolved_path);
|
||||
|
||||
var dir = try std.fs.cwd().openIterableDir(resolved_path, .{});
|
||||
defer dir.close();
|
||||
|
||||
var iter = try dir.walk(std.heap.c_allocator);
|
||||
|
@ -179,9 +199,9 @@ fn lAddFile(l: *c.lua_State) !c_int {
|
|||
|
||||
const inpath = ffi.luaCheckString(l, 1);
|
||||
|
||||
const outpath = if (argc >= 2) blk: {
|
||||
break :blk ffi.luaCheckString(l, 2);
|
||||
} else blk: {
|
||||
const outpath = if (argc >= 2)
|
||||
ffi.luaCheckString(l, 2)
|
||||
else blk: {
|
||||
if (std.mem.endsWith(u8, inpath, ".cgt")) {
|
||||
break :blk inpath[0 .. inpath.len - 4];
|
||||
}
|
||||
|
|
100
src/main.zig
100
src/main.zig
|
@ -1,11 +1,11 @@
|
|||
const std = @import("std");
|
||||
const args = @import("args");
|
||||
|
||||
const ffi = @import("ffi.zig");
|
||||
const c = ffi.c;
|
||||
|
||||
const luagen = @import("luagen.zig");
|
||||
const lapi = @import("lua_api.zig");
|
||||
const rootfile = @import("rootfile.zig");
|
||||
|
||||
const Parser = @import("Parser.zig");
|
||||
|
||||
|
@ -19,23 +19,85 @@ pub const std_options = struct {
|
|||
pub const log_level = if (@import("builtin").mode == .Debug) .debug else .info;
|
||||
};
|
||||
|
||||
pub fn main() !void {
|
||||
// TODO: add flag to emit generated lua files
|
||||
if (std.os.argv.len != 2) {
|
||||
// TODO: print usage
|
||||
std.log.err("Expected one argument.", .{});
|
||||
const Args = struct {
|
||||
/// Compile template to Lua for debugging.
|
||||
compile: ?[]const u8 = null,
|
||||
|
||||
pub const shorthands = .{
|
||||
.c = "compile",
|
||||
};
|
||||
};
|
||||
|
||||
const usage =
|
||||
\\==== Confgen - Config File Template Engine ====
|
||||
\\LordMZTE <lord@mzte.de>
|
||||
\\
|
||||
\\Options:
|
||||
\\ --compile, -c Compile a template to Lua instead of running. Useful for debugging.
|
||||
\\
|
||||
\\Usage:
|
||||
\\ confgen [CONFGENFILE] [OUTPATH] Generate configs according the the supplied configuration file.
|
||||
;
|
||||
|
||||
pub fn main() !u8 {
|
||||
run() catch |e| {
|
||||
switch (e) {
|
||||
error.InvalidArgs => {
|
||||
std.log.err(
|
||||
\\Invalid Arguments.
|
||||
\\{s}
|
||||
, .{usage});
|
||||
},
|
||||
//error.Explained => {},
|
||||
else => {
|
||||
std.log.err("UNEXPECTED: {s}", .{@errorName(e)});
|
||||
},
|
||||
}
|
||||
return 1;
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
pub fn run() !void {
|
||||
const arg = try args.parseForCurrentProcess(Args, std.heap.c_allocator, .print);
|
||||
defer arg.deinit();
|
||||
|
||||
if (arg.options.compile) |filepath| {
|
||||
if (arg.positionals.len != 0) {
|
||||
std.log.err("Expected 0 positional arguments, got {}.", .{arg.positionals.len});
|
||||
return error.InvalidArgs;
|
||||
}
|
||||
|
||||
const file = try std.fs.cwd().openFile(filepath, .{});
|
||||
defer file.close();
|
||||
|
||||
const content = try file.readToEndAlloc(std.heap.c_allocator, std.math.maxInt(usize));
|
||||
defer std.heap.c_allocator.free(content);
|
||||
|
||||
var parser = Parser{
|
||||
.str = content,
|
||||
.pos = 0,
|
||||
};
|
||||
|
||||
const tmpl = try luagen.generateLua(&parser, filepath);
|
||||
defer tmpl.deinit();
|
||||
|
||||
try std.io.getStdOut().writeAll(tmpl.content);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (arg.positionals.len != 2) {
|
||||
std.log.err("Expected 2 positional arguments, got {}.", .{arg.positionals.len});
|
||||
return error.InvalidArgs;
|
||||
}
|
||||
|
||||
const conf_dir = (try rootfile.findRootDir()) orelse {
|
||||
std.log.err("Couldn't find confgen.lua file!", .{});
|
||||
return error.RootfileNotFound;
|
||||
};
|
||||
defer std.heap.c_allocator.free(conf_dir);
|
||||
const cgfile = arg.positionals[0];
|
||||
|
||||
var state = lapi.CgState{
|
||||
.outpath = std.mem.span(std.os.argv[1]),
|
||||
.rootpath = conf_dir,
|
||||
.outpath = arg.positionals[1],
|
||||
.rootpath = std.fs.path.dirname(cgfile) orelse ".",
|
||||
.files = std.ArrayList(lapi.CgFile).init(std.heap.c_allocator),
|
||||
};
|
||||
defer state.deinit();
|
||||
|
@ -43,19 +105,13 @@ pub fn main() !void {
|
|||
const l = try lapi.initLuaState(&state);
|
||||
defer c.lua_close(l);
|
||||
|
||||
const conf_file_path = try std.fs.path.joinZ(
|
||||
std.heap.c_allocator,
|
||||
&.{ conf_dir, "confgen.lua" },
|
||||
);
|
||||
defer std.heap.c_allocator.free(conf_file_path);
|
||||
|
||||
if (c.luaL_loadfile(l, conf_file_path.ptr) != 0) {
|
||||
std.log.err("loading confgen.lua: {s}", .{ffi.luaToString(l, -1)});
|
||||
if (c.luaL_loadfile(l, cgfile.ptr) != 0) {
|
||||
std.log.err("loading confgen file: {s}", .{ffi.luaToString(l, -1)});
|
||||
return error.RootfileExec;
|
||||
}
|
||||
|
||||
if (c.lua_pcall(l, 0, 0, 0) != 0) {
|
||||
std.log.err("running confgen.lua: {s}", .{ffi.luaToString(l, -1)});
|
||||
std.log.err("running confgen file: {s}", .{ffi.luaToString(l, -1)});
|
||||
return error.RootfileExec;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
const std = @import("std");
|
||||
const c = @import("ffi.zig").c;
|
||||
|
||||
/// Tries to find the confgen.lua file by walking up the directory tree.
|
||||
/// Returns the directory path, NOT THE FILE PATH.
|
||||
/// Returned path is malloc'd
|
||||
pub fn findRootDir() !?[]const u8 {
|
||||
// TODO: walk upwards
|
||||
_ = std.fs.cwd().statFile("confgen.lua") catch |e| {
|
||||
if (e == error.FileNotFound) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return e;
|
||||
};
|
||||
|
||||
return try std.heap.c_allocator.dupe(u8, ".");
|
||||
}
|
Loading…
Reference in New Issue