const std = @import("std"); const Io = std.Io; const zlua = @import("zlua"); pub const Lua = zlua.Lua; const maivi = @import("../root.zig"); const helpers = maivi.helpers; /// * Pops from Stack: `0` /// * Pushes to Stack: `1` pub fn read(l: *Lua, io: Io, path: []const u8) !void { const dir = try Io.Dir.openDirAbsolute(io, maivi.config.root, .{}); defer dir.close(io); const contents = try helpers.read_file(io, maivi.allocator, dir, path); defer maivi.allocator.free(contents); var ctx: Context = .{ .path = path, .content = contents, }; try maivi.lua.trigger(l, Context, &ctx, .read_data, .{ .path = path, .pattern = path, }); if (ctx.content_ref) |ref| { _ = l.getIndexRaw(zlua.registry_index, ref); } else _ = l.pushString(contents); } const Context = struct { path: []const u8, content: []const u8, content_ref: ?i32 = null, ref: ?i32 = null, // reusable lua ref for hooks pub fn toLua(self: Context, l: *Lua) !void { // { url = ..., path = ..., content = ... } l.createTable(0, 2); // path _ = l.pushString(self.path); l.setField(-2, "path"); // path // content _ = l.pushString(self.content); l.setField(-2, "content"); // content // metatable try maivi.lua.setMethodTable(l, MT); } pub const MT = struct { pub fn use(l: *Lua) !i32 { l.argCheck(l.isTable(1), 1, "ctx"); l.argCheck(l.isString(2), 2, "string"); // -1 => content, -2 => ctx const ctx = blk: { const ltype_ptr = l.getField(1, "ptr"); defer l.pop(1); if (ltype_ptr != .light_userdata) return error.InvalidPtr; break :blk try l.toUserdata(Context, -1); }; ctx.content_ref = maivi.lua.toRef(l, -1); return 0; } }; };