Show Lua Errors on-screen, example.lua shows many squares

This commit is contained in:
RadsammyT 2026-05-21 20:21:19 -04:00
commit 4d33aa54b9
No known key found for this signature in database
3 changed files with 107 additions and 15 deletions

View file

@ -14,36 +14,51 @@
-- must be in the unsigned 32-bit integer range: 0 to 2^32-1.
-- clear() -- Clear the buffer.
-- }
--
-- A function named `draw()` must be declared in the script. This is ran every frame.
--
-- ]]
local SQUARE_WIDTH = 10
local SQUARE_HEIGHT = 5
local SQUARE_X = 0
local SQUARE_Y = 0
local SQUARE_COUNT = 25
local squares = {}
local SQUARE_VX = 1
local SQUARE_VY = 1
for i = 0, SQUARE_COUNT-1 do
local vx = 1
local vy = 1
if math.random(1, 2) == 2 then vx = -vx end
if math.random(1, 2) == 2 then vy = -vy end
squares[#squares+1] = {
x = math.random(1, ly.width - SQUARE_WIDTH),
y = math.random(1, ly.height - SQUARE_HEIGHT),
vx = vx,
vy = vy,
color = math.random(0xFFFFFF)
}
end
local timer = os.clock()
local color = math.random(0xFFFFFF)
function draw()
-- Rather than progressing the animation by frame, do it based on
-- seconds, like from os.clock().
if timer + 0.025 < os.clock() then
ly.clear()
SQUARE_X = SQUARE_X + SQUARE_VX
SQUARE_Y = SQUARE_Y + SQUARE_VY
for x = SQUARE_X, SQUARE_X + SQUARE_WIDTH do
for y = SQUARE_Y, SQUARE_Y + SQUARE_HEIGHT do
ly.putCell(string.byte(' '), 0, color, x, y)
for i, v in ipairs(squares) do
v.x = v.x + v.vx
v.y = v.y + v.vy
for x = v.x, v.x + SQUARE_WIDTH do
for y = v.y, v.y + SQUARE_HEIGHT do
ly.putCell(string.byte(' '), 0, v.color, x, y)
end
end
if v.x <= 0 then v.vx = 1; v.color = math.random(0xFFFFFF) end
if v.x + SQUARE_WIDTH >= ly.width-1 then v.vx = -1; v.color = math.random(0xFFFFFF) end
if v.y <= 0 then v.vy = 1; v.color = math.random(0xFFFFFF) end
if v.y + SQUARE_HEIGHT >= ly.height-1 then v.vy = -1; v.color = math.random(0xFFFFFF) end
end
if SQUARE_X <= 0 then SQUARE_VX = 1; color = math.random(0xFFFFFF) end
if SQUARE_X + SQUARE_WIDTH >= ly.width-1 then SQUARE_VX = -1; color = math.random(0xFFFFFF) end
if SQUARE_Y <= 0 then SQUARE_VY = 1; color = math.random(0xFFFFFF) end
if SQUARE_Y + SQUARE_HEIGHT >= ly.height-1 then SQUARE_VY = -1; color = math.random(0xFFFFFF) end
timer = os.clock()
end
end

View file

@ -12,15 +12,18 @@ const LyLua = @embedFile("ly.lua");
const Lua = @This();
allocator: Allocator,
instance: ?Widget = null,
lua: *zlua.Lua,
log: *LogFile,
terminal_buffer: *TerminalBuffer,
width: usize,
height: usize,
margin: usize,
io: std.Io,
lua_error: bool = false,
lua_str: ?[:0]const u8 = null,
pub fn init(
io: std.Io,
@ -28,14 +31,17 @@ pub fn init(
log: *LogFile,
buf: *TerminalBuffer,
file: ?[]const u8,
margin: u8,
) !Lua {
var self: Lua = .{
.lua = try zlua.Lua.init(alloc),
.allocator = alloc,
.terminal_buffer = buf,
.instance = null,
.log = log,
.width = 0,
.height = 0,
.margin = margin,
.io = io,
};
@ -53,11 +59,27 @@ pub fn init(
defer alloc.free(zf);
self.lua.doString(LyLua) catch {
const errorStr = self.lua.toString(-1) catch unreachable;
self.lua_str = try self.allocator.dupeSentinel(u8, errorStr, 0);
self.log.err(self.io, "Lua", "Lua Error: {s}", .{errorStr}) catch unreachable;
self.lua_error = true;
};
if (self.terminal_buffer.height != self.height or
self.terminal_buffer.width != self.width)
{
self.width = self.terminal_buffer.width;
self.height = self.terminal_buffer.height;
_ = self.lua.getGlobal("ly");
_ = self.lua.pushString("width");
self.lua.pushInteger(@intCast(self.terminal_buffer.width));
self.lua.setTable(-3);
_ = self.lua.pushString("height");
self.lua.pushInteger(@intCast(self.terminal_buffer.height));
self.lua.setTable(-3);
self.lua.setGlobal("ly");
}
self.lua.doFile(zf) catch {
const errorStr = self.lua.toString(-1) catch unreachable;
self.lua_str = try self.allocator.dupeSentinel(u8, errorStr, 0);
self.log.err(self.io, "Lua", "Lua Error: {s}", .{errorStr}) catch unreachable;
self.lua_error = true;
};
@ -84,12 +106,24 @@ fn draw(self: *Lua) void {
_ = self.lua.getGlobal("draw");
self.lua.protectedCall(.{}) catch {
const errorStr = self.lua.toString(-1) catch unreachable;
self.lua_str = std.mem.concatWithSentinel(
self.allocator,
u8,
&[_][]const u8{ "Cannot call draw(): ", errorStr },
0,
) catch unreachable;
self.log.err(self.io, "Lua", "Error (Cannot call draw()): {s}", .{errorStr}) catch unreachable;
self.lua_error = true;
};
const bufferType = self.lua.getGlobal("_BUFFER");
if (bufferType != .table) {
self.log.err(self.io, "Lua", "global '_BUFFER' must be a table: got {}", .{bufferType}) catch {};
self.lua_str = std.fmt.allocPrintSentinel(
self.allocator,
"global '_BUFFER' must be a table: got {}",
.{bufferType},
0,
) catch unreachable;
self.lua_error = true;
return;
}
@ -99,6 +133,12 @@ fn draw(self: *Lua) void {
// expect the value to be a table
const pos = self.lua.toInteger(-2) catch {
self.log.err(self.io, "Lua", "pos: cannot convert to integer", .{}) catch {};
self.lua_str = std.fmt.allocPrintSentinel(
self.allocator,
"pos: cannot convert to integer",
.{},
0,
) catch unreachable;
self.lua_error = true;
return;
};
@ -107,6 +147,12 @@ fn draw(self: *Lua) void {
_ = self.lua.getTable(-2);
const char = self.lua.toInteger(-1) catch {
self.log.err(self.io, "Lua", "char: cannot convert to integer", .{}) catch {};
self.lua_str = std.fmt.allocPrintSentinel(
self.allocator,
"char: cannot convert to integer",
.{},
0,
) catch unreachable;
self.lua_error = true;
return;
};
@ -115,6 +161,12 @@ fn draw(self: *Lua) void {
_ = self.lua.getTable(-2);
const fg = self.lua.toInteger(-1) catch {
self.log.err(self.io, "Lua", "fg: cannot convert to integer", .{}) catch {};
self.lua_str = std.fmt.allocPrintSentinel(
self.allocator,
"fg: cannot convert to integer",
.{},
0,
) catch unreachable;
self.lua_error = true;
return;
};
@ -123,6 +175,12 @@ fn draw(self: *Lua) void {
_ = self.lua.getTable(-2);
const bg = self.lua.toInteger(-1) catch {
self.log.err(self.io, "Lua", "bg: cannot convert to integer", .{}) catch {};
self.lua_str = std.fmt.allocPrintSentinel(
self.allocator,
"bg: cannot convert to integer",
.{},
0,
) catch unreachable;
self.lua_error = true;
return;
};
@ -138,6 +196,10 @@ fn draw(self: *Lua) void {
for (0..self.terminal_buffer.height) |y|
for (0..self.terminal_buffer.width) |x|
cell.put(x, y) catch {};
if (self.lua_str) |str|
for (str, 0..) |c, i| {
Cell.init(c, 0x00FFFFFF, 0).put(i, @divFloor(self.terminal_buffer.height, 2)) catch {};
};
}
}
@ -147,6 +209,12 @@ fn calculateTimeout(self: *Lua, _: *anyopaque) !?usize {
_ = self.lua.pushString("frame_delay"); // + 1
if (lyType != .table) {
try self.log.err(self.io, "Lua", "global 'ly' must be a table: got {}", .{lyType});
self.lua_str = std.fmt.allocPrintSentinel(
self.allocator,
"global 'ly' must be a table: got {}",
.{lyType},
0,
) catch unreachable;
self.lua_error = true;
self.lua.pop(-1);
self.lua.pop(-1);
@ -154,7 +222,13 @@ fn calculateTimeout(self: *Lua, _: *anyopaque) !?usize {
}
const frameDelayType = self.lua.getTable(-2); // neut
if (frameDelayType != .number) {
try self.log.err(self.io, "Lua", "'ly.frame_delay' must be a number: got {}", .{lyType});
try self.log.err(self.io, "Lua", "'ly.frame_delay' must be a number: got {}", .{frameDelayType});
self.lua_str = std.fmt.allocPrintSentinel(
self.allocator,
"'ly.frameDelayType' must be a table: got {}",
.{frameDelayType},
0,
) catch unreachable;
self.lua_error = true;
self.lua.pop(-1);
self.lua.pop(-1);
@ -167,6 +241,8 @@ fn calculateTimeout(self: *Lua, _: *anyopaque) !?usize {
}
fn deinit(self: *Lua) void {
if (self.lua_str) |str|
self.allocator.free(str);
self.lua.deinit();
}

View file

@ -1106,6 +1106,7 @@ pub fn main(init: std.process.Init) !void {
&state.log_file,
&state.buffer,
state.config.lua_animation_file,
state.config.edge_margin,
);
animation = lua.widget();
},