//! Cell type containing content and formatting for each character in the terminal screen. // TODO embrace `zg` dependency more due to utf-8 encoding cp: u21 = ' ', style: Style = .{ .emphasis = &.{} }, pub fn eql(this: Cell, other: Cell) bool { return this.cp == other.cp and this.style.eql(other.style); } pub fn reset(this: *Cell) void { this.style = .{ .emphasis = &.{} }; this.cp = ' '; } pub fn value(this: Cell, writer: anytype) !void { try this.style.value(writer, this.cp); } const std = @import("std"); const Style = @import("style.zig"); const Cell = @This(); test "ascii styled text" { const cells: [4]Cell = .{ .{ .cp = 'Y', .style = .{ .fg = .green, .bg = .grey, .emphasis = &.{} } }, .{ .cp = 'v', .style = .{ .emphasis = &.{ .bold, .underline } } }, .{ .cp = 'e', .style = .{ .emphasis = &.{.italic} } }, .{ .cp = 's', .style = .{ .fg = .light_green, .bg = .black, .emphasis = &.{.underline} } }, }; var string = std.ArrayList(u8).init(std.testing.allocator); defer string.deinit(); const writer = string.writer(); for (cells) |cell| { try cell.value(writer); } try std.testing.expectEqualSlices( u8, "\x1b[38;5;10;48;5;8;59mY\x1b[0m\x1b[39;49;59;1;4mv\x1b[0m\x1b[39;49;59;3me\x1b[0m\x1b[38;5;2;48;5;16;59;4ms\x1b[0m", string.items, ); } test "utf-8 styled text" { const cells: [4]Cell = .{ .{ .cp = '╭', .style = .{ .fg = .green, .bg = .grey, .emphasis = &.{} } }, .{ .cp = '─', .style = .{ .emphasis = &.{} } }, .{ .cp = '┄', .style = .{ .emphasis = &.{} } }, .{ .cp = '┘', .style = .{ .fg = .light_green, .bg = .black, .emphasis = &.{.underline} } }, }; var string = std.ArrayList(u8).init(std.testing.allocator); defer string.deinit(); const writer = string.writer(); for (cells) |cell| { try cell.value(writer); } try std.testing.expectEqualSlices( u8, "\x1b[38;5;10;48;5;8;59m╭\x1b[0m\x1b[39;49;59m─\x1b[0m\x1b[39;49;59m┄\x1b[0m\x1b[38;5;2;48;5;16;59;4m┘\x1b[0m", string.items, ); }