const std = @import("std"); const vaxis = @import("vaxis"); const ghostty_vt = @import("ghostty-vt"); extern "c" fn forkpty( amaster: *c_int, name: ?[*:0]u8, termp: ?*const anyopaque, winp: ?*const std.posix.winsize, ) c_int; extern "c" fn execvp( file: [*:0]const u8, argv: [*:null]const ?[*:0]const u8, ) c_int; // basic file navigation // basic shell io // basic layouting: for now following acme and ad // * /home/goblin/05-genizah/plan9port/src/cmd/acme // * /home/goblin/05-genizah/ad // * /usr/lib/zig // * ../03-plano // right click and enter on lines to open files at specified lines pub const Command = struct { prev: ?*Command = null, pub var value: union(enum) { close, ping, nop, quit, tick, key_press: vaxis.Key, winsize: vaxis.Winsize, mouse: vaxis.Mouse, } = .nop; }; const Loop = vaxis.Loop(@TypeOf(Command.value)); const MAX_FILES: usize = 0x200; fn ticker(io: std.Io, loop: *Loop) void { while (true) { io.sleep(.fromMilliseconds(2), .awake) catch return; _ = loop.tryPostEvent(.tick) catch return; } } fn fork_pty(argv: [:0]const u8, ws: std.posix.winsize) std.Io.File { var master: c_int = undefined; const pid = forkpty(&master, null, null, &ws); if (pid == 0) { _ = execvp(argv, &.{}); std.process.exit(0); } // not sure about the false here const f: std.Io.File = .{ .handle = master, .flags = .{ .nonblocking = false } }; return f; } const nrows = 16; const ncols = 80; pub fn main(init: std.process.Init) !void { const io = init.io; const gpa = init.gpa; var term: ghostty_vt.Terminal = try .init(gpa, .{ .cols = ncols, .rows = nrows, }); defer term.deinit(gpa); var tty_reader = term.vtStream(); defer tty_reader.deinit(); // const str = try term.plainString(gpa); var tty_buf: [0x10000]u8 = undefined; var tty = try vaxis.Tty.init(io, &tty_buf); var vx = try vaxis.init(io, gpa, init.environ_map, .{}); defer vx.deinit(gpa, tty.writer()); const pty_master = fork_pty("/usr/bin/bash", .{ .row = nrows, .col = ncols, .xpixel = 0, .ypixel = 0, }); var write_buf: [0x100]u8 = undefined; var writer = pty_master.writer(io, &write_buf); std.debug.print("written {}\n", .{try writer.interface.write("ls -la /\r\n")}); try writer.flush(); var read_buf: [0x400]u8 = undefined; var reader = pty_master.readerStreaming(io, &read_buf); try io.sleep(.fromMilliseconds(200), .real); const str = try reader.interface.readAlloc(gpa, 0x400); tty_reader.nextSlice(str); defer gpa.free(str); const tty_str = try term.plainString(gpa); defer gpa.free(tty_str); // std.debug.print("{s}", .{tty_str}); // try vx.setMouseMode(tty.writer(), true); var loop: Loop = .init(io, &tty, &vx); try loop.start(); defer loop.stop(); while (true) { const event = try loop.nextEvent(); const win = vx.window(); const win_child = win.child(.{ .border = .{ .where = .all }, .height = nrows, .width = ncols, }); _ = win_child.printSegment(.{ .text = tty_str }, .{}); switch (event) { .key_press => |key| { if (key.matches('c', .{ .ctrl = true })) { break; } }, .winsize => |ws| try vx.resize(gpa, tty.writer(), ws), else => {}, } try vx.render(tty.writer()); } }