╭ changed ╮ │build.zig│ ╰─────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────╮ │32 │ │33 break :blk install_exe; │ │34 }; │ │35 + │ │36 + // wasm │ │37 + { │ │38 + const wasm_target = b.resolveTargetQuery(.{ │ │39 + .cpu_arch = .wasm32, │ │40 + .os_tag = .freestanding, │ │41 + }); │ │42 + │ │43 + const exe = b.addExecutable(.{ │ │44 + .name = "haxy", │ │45 + .root_module = b.createModule(.{ │ │46 + .root_source_file = b.path("src/main_wasm.zig"), │ │47 + .target = wasm_target, │ │48 + .optimize = .ReleaseSmall, │ │49 + }), │ │50 + }); │ │51 + exe.root_module.addImport("xit", b.dependency("xit", .{}).module("xit"));│ │52 + │ │53 + exe.global_base = 6560; │ │54 + exe.entry = .disabled; │ │55 + exe.rdynamic = true; │ │56 + exe.import_memory = false; │ │57 + exe.export_memory = true; │ │58 + exe.stack_size = std.wasm.page_size; │ │59 + │ │60 + const initial_pages = 16; │ │61 + const max_pages = 256; │ │62 + exe.initial_memory = std.wasm.page_size * initial_pages; │ │63 + exe.max_memory = std.wasm.page_size * max_pages; │ │64 │ │65 + b.installArtifact(exe); │ │66 + │ │67 + const wasm_step = b.step("wasm", "Generate the wasm"); │ │68 + wasm_step.dependOn(&exe.step); │ │69 + wasm_step.dependOn(b.getInstallStep()); │ │70 + } │ │71 + │ │72 // module for using haxy as a library │ │73 // (the commands below consume haxy this way) │ │74 const haxy = b.addModule("haxy", .{ │ ╰─────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────╮ │ 8 const Grid = xitui.grid.Grid; │ │ 9 const Focus = xitui.focus.Focus; │ │10 │ │11 -pub fn run(io: std.Io, allocator: std.mem.Allocator) !void { │ │11 +const html_width = 80; │ │12 +const html_height = 24; │ │13 + │ │14 +pub fn initRoot(allocator: std.mem.Allocator) !Widget { │ │15 var root = Widget{ .widget_list = try WidgetList.init(allocator) }; │ │13 - defer root.deinit(); │ │16 + errdefer root.deinit(); │ │17 + │ │18 + try buildRoot(&root, html_width, html_height); │ │19 + if (root.getFocus().child_id) |child_id| { │ │20 + try root.getFocus().setFocus(child_id); │ │21 + } │ │22 + │ │23 + return root; │ │24 +} │ │25 │ │26 +pub fn buildRoot(root: *Widget, width: usize, height: usize) !void { │ │27 try root.build(.{ │ │28 .min_size = .{ .width = null, .height = null }, │ │17 - .max_size = .{ .width = 10, .height = 10 }, │ │29 + .max_size = .{ .width = width, .height = height }, │ │30 }, root.getFocus()); │ │19 - if (root.getFocus().child_id) |child_id| { │ │20 - try root.getFocus().setFocus(child_id); │ │31 +} │ │32 + │ │33 +pub fn generateHtml(allocator: std.mem.Allocator, root: *Widget) ![]const u8 { │ │34 + const grid = root.getGrid() orelse return error.MissingGrid; │ │35 + │ │36 + var out: std.ArrayList(u8) = .empty; │ │37 + errdefer out.deinit(allocator); │ │38 + │ │39 + for (0..grid.size.height) |y| { │ │40 + for (0..grid.size.width) |x| { │ │41 + const rune = grid.cells.items[try grid.cells.at(.{ y, x })].rune orelse " ";│ │42 + try appendEscapedHtml(allocator, &out, rune); │ │43 + } │ │44 + try out.append(allocator, '\n'); │ │45 } │ │46 + │ │47 + return try out.toOwnedSlice(allocator); │ │48 +} │ │49 │ │50 +pub fn run(io: std.Io, allocator: std.mem.Allocator) !void { │ │51 + var root = try initRoot(allocator); │ │52 + defer root.deinit(); │ │53 + │ │54 var terminal = try term.Terminal.init(io, allocator); │ │55 defer terminal.deinit(io); │ │56 │ ╰────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │69 try root.input(key, root.getFocus()); │ │70 } │ │71 │ │41 - try root.build(.{ │ │42 - .min_size = .{ .width = null, .height = null }, │ │43 - .max_size = .{ .width = last_size.width, .height = last_size.height }, │ │44 - }, root.getFocus()); │ │72 + try buildRoot(&root, last_size.width, last_size.height); │ │73 │ │74 try std.Io.sleep(io, .fromMilliseconds(5), .real); │ │75 + } │ │76 +} │ │77 + │ │78 +fn appendEscapedHtml(allocator: std.mem.Allocator, out: *std.ArrayList(u8), input: []const u8) !void {│ │79 + for (input) |ch| { │ │80 + switch (ch) { │ │81 + '&' => try out.appendSlice(allocator, "&amp;"), │ │82 + '<' => try out.appendSlice(allocator, "&lt;"), │ │83 + '>' => try out.appendSlice(allocator, "&gt;"), │ │84 + '"' => try out.appendSlice(allocator, "&quot;"), │ │85 + '\'' => try out.appendSlice(allocator, "&#39;"), │ │86 + else => try out.append(allocator, ch), │ │87 + } │ │88 } │ │89 } │ │90 │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ added ──────────╮ │src/main_wasm.zig│ ╰─────────────────╯