1const std = @import("std");
2
3pub const ascii = enum(u7) {
4 NUL,
5 SOH,
6 STX,
7 ETX,
8 EOT,
9 ENQ,
10 ACK,
11 BEL,
12 BS,
13 TAB,
14 LF,
15 VT,
16 FF,
17 CR,
18 SO,
19 SI,
20 DLE,
21 DC1,
22 DC2,
23 DC3,
24 DC4,
25 NAK,
26 SYN,
27 ETB,
28 CAN,
29 EM,
30 SUB,
31 ESC,
32 FS,
33 GS,
34 RS,
35 US,
36 _,
37
38 pub fn s(self: ascii) [1]u8 {
39 return .{@intFromEnum(self)};
40 }
41};
42
43pub const escape = struct {
44 pub const SS2 = ascii.ESC.s() ++ "N";
45 pub const SS3 = ascii.ESC.s() ++ "O";
46 pub const DCS = ascii.ESC.s() ++ "P";
47 pub const CSI = ascii.ESC.s() ++ "[";
48 pub const ST = ascii.ESC.s() ++ "\\";
49 pub const OSC = ascii.ESC.s() ++ "]";
50 pub const SOS = ascii.ESC.s() ++ "X";
51 pub const PM = ascii.ESC.s() ++ "^";
52 pub const APC = ascii.ESC.s() ++ "_";
53 pub const RIS = ascii.ESC.s() ++ "c";
54};
55
56fn make_csi_sequence(comptime c: []const u8, comptime x: anytype) []const u8 {
57 return comptime escape.CSI ++ _join(";", arr_i_to_s(x)) ++ c;
58}
59
60fn arr_i_to_s(x: anytype) [][]const u8 {
61 comptime {
62 var res: [x.len][]const u8 = undefined;
63 for (x, 0..) |item, i| {
64 res[i] = std.fmt.comptimePrint("{}", .{item});
65 }
66 return &res;
67 }
68}
69
70pub const csi = struct {
71 pub fn CursorUp(comptime n: i32) []const u8 {
72 return make_csi_sequence("A", .{n});
73 }
74 pub fn CursorDown(comptime n: i32) []const u8 {
75 return make_csi_sequence("B", .{n});
76 }
77 pub fn CursorForward(comptime n: i32) []const u8 {
78 return make_csi_sequence("C", .{n});
79 }
80 pub fn CursorBack(comptime n: i32) []const u8 {
81 return make_csi_sequence("D", .{n});
82 }
83 pub fn CursorNextLine(comptime n: i32) []const u8 {
84 return make_csi_sequence("E", .{n});
85 }
86 pub fn CursorPrevLine(comptime n: i32) []const u8 {
87 return make_csi_sequence("F", .{n});
88 }
89 pub fn CursorHorzAbs(comptime n: i32) []const u8 {
90 return make_csi_sequence("G", .{n});
91 }
92 pub fn CursorPos(comptime n: i32, m: i32) []const u8 {
93 return make_csi_sequence("H", .{ n, m });
94 }
95 pub fn EraseInDisplay(comptime n: i32) []const u8 {
96 return make_csi_sequence("J", .{n});
97 }
98 pub fn EraseInLine(comptime n: i32) []const u8 {
99 return make_csi_sequence("K", .{n});
100 }
101 pub fn ScrollUp(comptime n: i32) []const u8 {
102 return make_csi_sequence("S", .{n});
103 }
104 pub fn ScrollDown(comptime n: i32) []const u8 {
105 return make_csi_sequence("T", .{n});
106 }
107 pub fn HorzVertPos(comptime n: i32, m: i32) []const u8 {
108 return make_csi_sequence("f", .{ n, m });
109 }
110 pub fn SGR(comptime ns: anytype) []const u8 {
111 return make_csi_sequence("m", ns);
112 }
113};
114
115pub const style = struct {
116 pub const ResetAll = csi.SGR(.{0});
117
118 pub const Bold = csi.SGR(.{1});
119 pub const Faint = csi.SGR(.{2});
120 pub const Italic = csi.SGR(.{3});
121 pub const Underline = csi.SGR(.{4});
122 pub const BlinkSlow = csi.SGR(.{5});
123 pub const BlinkFast = csi.SGR(.{6});
124
125 pub const ResetFont = csi.SGR(.{10});
126 pub const Font1 = csi.SGR(.{11});
127 pub const Font2 = csi.SGR(.{12});
128 pub const Font3 = csi.SGR(.{13});
129 pub const Font4 = csi.SGR(.{14});
130 pub const Font5 = csi.SGR(.{15});
131 pub const Font6 = csi.SGR(.{16});
132 pub const Font7 = csi.SGR(.{17});
133 pub const Font8 = csi.SGR(.{18});
134 pub const Font9 = csi.SGR(.{19});
135
136 pub const UnderlineDouble = csi.SGR(.{21});
137 pub const ResetIntensity = csi.SGR(.{22});
138 pub const ResetItalic = csi.SGR(.{23});
139 pub const ResetUnderline = csi.SGR(.{24});
140 pub const ResetBlink = csi.SGR(.{25});
141
142 pub const FgBlack = csi.SGR(.{30});
143 pub const FgRed = csi.SGR(.{31});
144 pub const FgGreen = csi.SGR(.{32});
145 pub const FgYellow = csi.SGR(.{33});
146 pub const FgBlue = csi.SGR(.{34});
147 pub const FgMagenta = csi.SGR(.{35});
148 pub const FgCyan = csi.SGR(.{36});
149 pub const FgWhite = csi.SGR(.{37});
150 // Fg8bit = func(n int) string { return csi.SGR(38, 5, n) }
151 // Fg24bit = func(r, g, b int) string { return csi.SGR(38, 2, r, g, b) }
152 pub const ResetFgColor = csi.SGR(.{39});
153
154 pub const BgBlack = csi.SGR(.{40});
155 pub const BgRed = csi.SGR(.{41});
156 pub const BgGreen = csi.SGR(.{42});
157 pub const BgYellow = csi.SGR(.{43});
158 pub const BgBlue = csi.SGR(.{44});
159 pub const BgMagenta = csi.SGR(.{45});
160 pub const BgCyan = csi.SGR(.{46});
161 pub const BgWhite = csi.SGR(.{47});
162 // Bg8bit = func(n int) string { return csi.SGR(48, 5, n) }
163 // Bg24bit = func(r, g, b int) string { return csi.SGR(48, 2, r, g, b) }
164 pub const ResetBgColor = csi.SGR(.{49});
165
166 pub const Framed = csi.SGR(.{51});
167 pub const Encircled = csi.SGR(.{52});
168 pub const Overlined = csi.SGR(.{53});
169 pub const ResetFrameEnci = csi.SGR(.{54});
170 pub const ResetOverlined = csi.SGR(.{55});
171};
172
173pub const color = struct {
174 pub const Color = enum(u8) {
175 Black,
176 Red,
177 Green,
178 Yellow,
179 Blue,
180 Magenta,
181 Cyan,
182 White,
183 };
184
185 pub fn Fg(s: Color, comptime m: []const u8) []const u8 {
186 return csi.SGR(.{30 + @intFromEnum(s)}) ++ m ++ style.ResetFgColor;
187 }
188
189 pub fn Bg(s: Color, comptime m: []const u8) []const u8 {
190 return csi.SGR(.{40 + @intFromEnum(s)}) ++ m ++ style.ResetBgColor;
191 }
192
193 pub fn Bold(comptime m: []const u8) []const u8 {
194 return style.Bold ++ m ++ style.ResetIntensity;
195 }
196
197 pub fn Faint(comptime m: []const u8) []const u8 {
198 return style.Faint ++ m ++ style.ResetIntensity;
199 }
200
201 pub fn Italic(comptime m: []const u8) []const u8 {
202 return style.Italic ++ m ++ style.ResetItalic;
203 }
204
205 pub fn Underline(comptime m: []const u8) []const u8 {
206 return style.Underline ++ m ++ style.ResetUnderline;
207 }
208};
209
210//
211// private
212//
213
214fn _join(comptime delim: []const u8, comptime xs: [][]const u8) []const u8 {
215 var buf: []const u8 = "";
216 for (xs, 0..) |x, i| {
217 buf = buf ++ x;
218 if (i < xs.len - 1) buf = buf ++ delim;
219 }
220 return buf;
221}