diff --git a/src/main.zig b/src/main.zig index 140170d..c1ad99b 100644 --- a/src/main.zig +++ b/src/main.zig @@ -68,6 +68,7 @@ pub fn main() !void { pub const Terminal = struct { tty: fs.File, + buffered_writer: io.BufferedWriter(4096, fs.File.Writer), original_termios: os.linux.termios, info: Info, allocator: mem.Allocator, @@ -79,6 +80,7 @@ pub const Terminal = struct { pub fn init(allocator: mem.Allocator) !Terminal { var term = Terminal{ .tty = try fs.openFileAbsolute("/dev/tty", .{ .mode = .read_write }), + .buffered_writer = undefined, .original_termios = undefined, .info = try Info.init(allocator), .allocator = allocator, @@ -87,6 +89,7 @@ pub const Terminal = struct { }; errdefer term.tty.close(); errdefer term.info.deinit(); + term.buffered_writer = io.bufferedWriter(term.tty.writer()); try term.uncook(); try attachSignalHandlers(); try term.updateWinSize(); @@ -100,6 +103,7 @@ pub const Terminal = struct { self.box.deinit(); self.cook() catch @panic("failed to restore termios"); self.cursorShow() catch @panic("failed to unhide cursor"); + self.buffered_writer.flush() catch @panic("couldn't flush output buffer"); self.tty.close(); self.info.deinit(); } @@ -214,76 +218,77 @@ pub const Terminal = struct { pub fn draw(self: *Terminal) !void { if (self.box.dirty) try self.clearScreen(); try self.box.draw(self); + try self.buffered_writer.flush(); } pub fn print(self: *Terminal, comptime format: []const u8, args: anytype) !void { const formatted = try fmt.allocPrint(self.allocator, format, args); defer self.allocator.free(formatted); - try self.tty.writeAll(formatted); + try self.buffered_writer.writer().writeAll(formatted); } pub fn cursorShow(self: *Terminal) !void { - try self.info.writeString(.cursor_visible, self.tty.writer(), &[_]u32{}); + try self.info.writeString(.cursor_visible, self.buffered_writer.writer(), &[_]u32{}); } pub fn cursorHide(self: *Terminal) !void { - try self.info.writeString(.cursor_invisible, self.tty.writer(), &[_]u32{}); + try self.info.writeString(.cursor_invisible, self.buffered_writer.writer(), &[_]u32{}); } pub fn cursorUp(self: *Terminal) !void { - try self.info.writeString(.cursor_up, self.tty.writer(), &[_]u32{}); + try self.info.writeString(.cursor_up, self.buffered_writer.writer(), &[_]u32{}); } pub fn cursorDown(self: *Terminal) !void { - try self.info.writeString(.cursor_down, self.tty.writer(), &[_]u32{}); + try self.info.writeString(.cursor_down, self.buffered_writer.writer(), &[_]u32{}); } pub fn cursorLeft(self: *Terminal) !void { - try self.info.writeString(.cursor_left, self.tty.writer(), &[_]u32{}); + try self.info.writeString(.cursor_left, self.buffered_writer.writer(), &[_]u32{}); } pub fn cursorRight(self: *Terminal) !void { - try self.info.writeString(.cursor_right, self.tty.writer(), &[_]u32{}); + try self.info.writeString(.cursor_right, self.buffered_writer.writer(), &[_]u32{}); } pub fn cursorSet(self: *Terminal, x: u32, y: u32) !void { - try self.info.writeString(.cursor_address, self.tty.writer(), &[_]u32{ y, x }); + try self.info.writeString(.cursor_address, self.buffered_writer.writer(), &[_]u32{ y, x }); } pub fn blinkOn(self: *Terminal) !void { - try self.info.writeString(.enter_blink_mode, self.tty.writer(), &[_]u32{}); + try self.info.writeString(.enter_blink_mode, self.buffered_writer.writer(), &[_]u32{}); } pub fn blinkOff(self: *Terminal) !void { - try self.info.writeString(.exit_blink_mode, self.tty.writer(), &[_]u32{}); + try self.info.writeString(.exit_blink_mode, self.buffered_writer.writer(), &[_]u32{}); } pub fn boldOn(self: *Terminal) !void { - try self.info.writeString(.enter_bold_mode, self.tty.writer(), &[_]u32{}); + try self.info.writeString(.enter_bold_mode, self.buffered_writer.writer(), &[_]u32{}); } pub fn boldOff(self: *Terminal) !void { - try self.info.writeString(.exit_bold_mode, self.tty.writer(), &[_]u32{}); + try self.info.writeString(.exit_bold_mode, self.buffered_writer.writer(), &[_]u32{}); } pub fn italicsOn(self: *Terminal) !void { - try self.info.writeString(.enter_italics_mode, self.tty.writer(), &[_]u32{}); + try self.info.writeString(.enter_italics_mode, self.buffered_writer.writer(), &[_]u32{}); } pub fn italicsOff(self: *Terminal) !void { - try self.info.writeString(.exit_italics_mode, self.tty.writer(), &[_]u32{}); + try self.info.writeString(.exit_italics_mode, self.buffered_writer.writer(), &[_]u32{}); } pub fn underlineOn(self: *Terminal) !void { - try self.info.writeString(.enter_underline_mode, self.tty.writer(), &[_]u32{}); + try self.info.writeString(.enter_underline_mode, self.buffered_writer.writer(), &[_]u32{}); } pub fn underlineOff(self: *Terminal) !void { - try self.info.writeString(.exit_underline_mode, self.tty.writer(), &[_]u32{}); + try self.info.writeString(.exit_underline_mode, self.buffered_writer.writer(), &[_]u32{}); } pub fn clearScreen(self: *Terminal) !void { - try self.info.writeString(.clear_screen, self.tty.writer(), &[_]u32{}); + try self.info.writeString(.clear_screen, self.buffered_writer.writer(), &[_]u32{}); } // pub fn clearRegion(self: *Terminal, x: u32, y: u32, width: u32, height: u32) !void { @@ -297,7 +302,7 @@ pub const Terminal = struct { // } pub fn setFg(self: *Terminal, color: Color) !void { - try self.info.writeString(.set_rgb_foreground, self.tty.writer(), &[_]u32{ + try self.info.writeString(.set_rgb_foreground, self.buffered_writer.writer(), &[_]u32{ @intFromFloat(color.r * 0xff), @intFromFloat(color.g * 0xff), @intFromFloat(color.b * 0xff), @@ -305,7 +310,7 @@ pub const Terminal = struct { } pub fn setBg(self: *Terminal, color: Color) !void { - try self.info.writeString(.set_rgb_background, self.tty.writer(), &[_]u32{ + try self.info.writeString(.set_rgb_background, self.buffered_writer.writer(), &[_]u32{ @intFromFloat(color.r * 0xff), @intFromFloat(color.g * 0xff), @intFromFloat(color.b * 0xff),