const std = @import("std"); const fern = @import("fern"); const zlua = @import("zlua"); const Lua = zlua.Lua; const maivi = @import("../root.zig"); pub fn lua_opendisplay(l: *Lua) !i32 { l.createTable(0, 2); l.pushFunction(zlua.wrap(elem)); l.setField(-2, "elem"); l.pushFunction(zlua.wrap(attr)); l.setField(-2, "attr"); return 1; } pub fn elem(l: *Lua) !i32 { if (l.isFunction(-1)) { try maivi.lua.pcall(l, .{ .results = 1 }); return try elem(l); } if (l.isTable(-1)) { return try recursive_concat(l, null); } if (l.isBoolean(-1)) { const str = switch (l.toBoolean(-1)) { true => "true", false => "false", }; _ = l.pushString(str); return 1; } l.pushValue(-1); _ = try l.toString(-1); return 1; } pub fn attr(l: *Lua) !i32 { if (l.isTable(-1)) { return try recursive_concat(l, " "); } if (l.isBoolean(-1)) { const str = switch (l.toBoolean(-1)) { true => "true", false => "false", }; _ = l.pushString(str); return 1; } l.pushValue(-1); _ = try l.toString(-1); return 1; } const Error = error{ ExpectedString, ExpectedTable } || error{ LuaRuntime, LuaMsgHandler } || std.mem.Allocator.Error; fn recursive_concat(l: *Lua, sep: ?[]const u8) Error!i32 { var arena: std.heap.ArenaAllocator = .init(maivi.allocator); defer arena.deinit(); var allocator = arena.allocator(); const slices = blk: { l.pushValue(-1); if (!l.isTable(-1)) return error.ExpectedTable; var slices: std.ArrayList([]const u8) = try .initCapacity(maivi.allocator, 16); errdefer slices.deinit(maivi.allocator); l.pushNil(); // stack now contains: -1 => nil; -2 => table while (l.next(-2)) { // stack now contains: -1 => value; -2 => key; -3 => table _ = try elem(l); // stack now contains: -1 => value (parsed); -2 => value; -3 => key; -4 => table const vz = try l.toString(-1); const v = try allocator.dupe(u8, vz); try slices.append(maivi.allocator, v); // pop value + copy, leaving original key l.pop(2); // stack now contains: -1 => key; -2 => table } l.pop(1); break :blk try slices.toOwnedSlice(maivi.allocator); }; defer maivi.allocator.free(slices); const str = if (sep) |s| try std.mem.join(maivi.allocator, s, slices) else try std.mem.concat(maivi.allocator, u8, slices); defer maivi.allocator.free(str); _ = l.pushString(str); return 1; }