diff --git a/examples/main.zig b/examples/main.zig index 3a21ee5..5abbf5f 100644 --- a/examples/main.zig +++ b/examples/main.zig @@ -22,12 +22,18 @@ pub fn main() !void { try vx.enterAltScreen(); + var color_idx: u8 = 0; const msg = "Hello, world!"; outer: while (true) { const event = vx.nextEvent(); log.debug("event: {}\r\n", .{event}); switch (event) { .key_press => |key| { + if (color_idx == 255) { + color_idx = 0; + } else { + color_idx += 1; + } if (key.codepoint == 'c' and key.mods.ctrl) { break :outer; } @@ -42,7 +48,10 @@ pub fn main() !void { win.clear(); const child = win.initChild(win.width / 2 - msg.len / 2, win.height / 2, .expand, .expand); for (msg, 0..) |_, i| { - const cell: Cell = .{ .char = .{ .grapheme = msg[i .. i + 1] } }; + const cell: Cell = .{ + .char = .{ .grapheme = msg[i .. i + 1] }, + .style = .{ .fg = .{ .index = color_idx } }, + }; child.writeCell(i, 0, cell); } try vx.render(); diff --git a/src/cell.zig b/src/cell.zig index e57261f..7c3daef 100644 --- a/src/cell.zig +++ b/src/cell.zig @@ -24,6 +24,14 @@ pub const Style = struct { ul_style: Underline = .off, url: ?[]const u8 = null, url_params: ?[]const u8 = null, + + bold: bool = false, + dim: bool = false, + italic: bool = false, + blink: bool = false, + reverse: bool = false, + invisible: bool = false, + strikethrough: bool = false, }; pub const Color = union(enum) { diff --git a/src/ctlseqs.zig b/src/ctlseqs.zig index 6089ef3..59f6095 100644 --- a/src/ctlseqs.zig +++ b/src/ctlseqs.zig @@ -11,7 +11,52 @@ pub const csi_u_pop = "\x1b[ _ = try tty.write(ctlseqs.fg_reset), + .index => |idx| { + switch (idx) { + 0...7 => try std.fmt.format(tty.writer(), ctlseqs.fg_base, .{idx}), + 8...15 => try std.fmt.format(tty.writer(), ctlseqs.fg_bright, .{idx}), + else => try std.fmt.format(tty.writer(), ctlseqs.fg_indexed, .{idx}), + } + }, + .rgb => |rgb| { + try std.fmt.format(tty.writer(), ctlseqs.fg_rgb, .{ rgb[0], rgb[1], rgb[2] }); + }, + } + } + // background + if (!std.meta.eql(cursor.bg, cell.style.bg)) { + switch (cell.style.bg) { + .default => _ = try tty.write(ctlseqs.bg_reset), + .index => |idx| { + switch (idx) { + 0...7 => try std.fmt.format(tty.writer(), ctlseqs.bg_base, .{idx}), + 8...15 => try std.fmt.format(tty.writer(), ctlseqs.bg_bright, .{idx}), + else => try std.fmt.format(tty.writer(), ctlseqs.bg_indexed, .{idx}), + } + }, + .rgb => |rgb| { + try std.fmt.format(tty.writer(), ctlseqs.bg_rgb, .{ rgb[0], rgb[1], rgb[2] }); + }, + } + } + // underline color + if (!std.meta.eql(cursor.ul, cell.style.ul)) { + switch (cell.style.bg) { + .default => _ = try tty.write(ctlseqs.ul_reset), + .index => |idx| { + try std.fmt.format(tty.writer(), ctlseqs.ul_indexed, .{idx}); + }, + .rgb => |rgb| { + try std.fmt.format(tty.writer(), ctlseqs.ul_rgb, .{ rgb[0], rgb[1], rgb[2] }); + }, + } + } + // underline style + if (!std.meta.eql(cursor.ul_style, cell.style.ul_style)) { + const seq = switch (cell.style.ul_style) { + .off => ctlseqs.ul_off, + .single => ctlseqs.ul_single, + .double => ctlseqs.ul_double, + .curly => ctlseqs.ul_curly, + .dotted => ctlseqs.ul_dotted, + .dashed => ctlseqs.ul_dashed, + }; + _ = try tty.write(seq); + } + // bold + if (cursor.bold != cell.style.bold) { + const seq = switch (cell.style.bold) { + true => ctlseqs.bold_set, + false => ctlseqs.bold_dim_reset, + }; + _ = try tty.write(seq); + if (cell.style.dim) { + _ = try tty.write(ctlseqs.dim_set); + } + } + // dim + if (cursor.dim != cell.style.dim) { + const seq = switch (cell.style.dim) { + true => ctlseqs.dim_set, + false => ctlseqs.bold_dim_reset, + }; + _ = try tty.write(seq); + if (cell.style.bold) { + _ = try tty.write(ctlseqs.bold_set); + } + } + // dim + if (cursor.italic != cell.style.italic) { + const seq = switch (cell.style.italic) { + true => ctlseqs.italic_set, + false => ctlseqs.italic_reset, + }; + _ = try tty.write(seq); + } + // dim + if (cursor.blink != cell.style.blink) { + const seq = switch (cell.style.blink) { + true => ctlseqs.blink_set, + false => ctlseqs.blink_reset, + }; + _ = try tty.write(seq); + } + // reverse + if (cursor.reverse != cell.style.reverse) { + const seq = switch (cell.style.reverse) { + true => ctlseqs.reverse_set, + false => ctlseqs.reverse_reset, + }; + _ = try tty.write(seq); + } + // invisible + if (cursor.invisible != cell.style.invisible) { + const seq = switch (cell.style.invisible) { + true => ctlseqs.invisible_set, + false => ctlseqs.invisible_reset, + }; + _ = try tty.write(seq); + } + // strikethrough + if (cursor.strikethrough != cell.style.strikethrough) { + const seq = switch (cell.style.strikethrough) { + true => ctlseqs.strikethrough_set, + false => ctlseqs.strikethrough_reset, + }; + _ = try tty.write(seq); + } + + // url + if (!std.meta.eql(cursor.url, cell.style.url)) { + const url = cell.style.url orelse ""; + var ps = cell.style.url_params orelse ""; + if (url.len == 0) { + // Empty out the params no matter what if we don't have + // a url + ps = ""; + } + try std.fmt.format(tty.writer(), ctlseqs.osc8, .{ ps, url }); + } _ = try tty.write(cell.char.grapheme); } }