Skip to content

Commit 79c7fe7

Browse files
committed
build: make custom use of ansi codes and share color writer
1 parent 4778001 commit 79c7fe7

File tree

3 files changed

+145
-152
lines changed

3 files changed

+145
-152
lines changed

build/benchmark.zig

Lines changed: 2 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,15 @@
11
const builtin = @import("builtin");
2+
const color = @import("color.zig");
23
const std = @import("std");
34

45
const Allocator = std.mem.Allocator;
6+
const ColorWriter = color.ColorWriter;
57
const PriorityDequeue = std.PriorityDequeue;
68
const TestFn = std.builtin.TestFn;
7-
const TerminalColors = std.io.tty.Color;
8-
const ZigColor = std.zig.Color;
99

1010
/// Wraps the stderr with our color stream.
1111
const ColorWriterStream = ColorWriter(@TypeOf(std.io.getStdErr().writer()));
1212

13-
/// Custom writer that we use to write tests result and with specific tty colors.
14-
fn ColorWriter(comptime UnderlayingWriter: type) type {
15-
return struct {
16-
/// Set of possible errors from this writer.
17-
const Error = UnderlayingWriter.Error || std.os.windows.SetConsoleTextAttributeError;
18-
19-
const Writer = std.io.Writer(*Self, Error, write);
20-
const Self = @This();
21-
22-
/// Initial empty state.
23-
pub const empty: Self = .{
24-
.color = .auto,
25-
.underlaying_writer = std.io.getStdErr().writer(),
26-
.next_color = .reset,
27-
};
28-
29-
/// The writer that we will use to write to.
30-
underlaying_writer: UnderlayingWriter,
31-
/// Zig color tty config.
32-
color: ZigColor,
33-
/// Next tty color to apply in the stream.
34-
next_color: TerminalColors,
35-
36-
pub fn writer(self: *Self) Writer {
37-
return .{ .context = self };
38-
}
39-
/// Write function that will write to the stream with the `next_color`.
40-
pub fn write(self: *Self, bytes: []const u8) Error!usize {
41-
if (bytes.len == 0)
42-
return bytes.len;
43-
44-
try self.applyColor(self.next_color);
45-
try self.writeNoColor(bytes);
46-
try self.applyColor(.reset);
47-
48-
return bytes.len;
49-
}
50-
/// Sets the next color in the stream
51-
pub fn setNextColor(self: *Self, next: TerminalColors) void {
52-
self.next_color = next;
53-
}
54-
/// Writes the next color to the stream.
55-
pub fn applyColor(self: *Self, color: TerminalColors) Error!void {
56-
try self.color.renderOptions().ttyconf.setColor(self.underlaying_writer, color);
57-
}
58-
/// Writes to the stream without colors.
59-
pub fn writeNoColor(self: *Self, bytes: []const u8) UnderlayingWriter.Error!void {
60-
if (bytes.len == 0)
61-
return;
62-
63-
try self.underlaying_writer.writeAll(bytes);
64-
}
65-
};
66-
}
67-
6813
/// Custom benchmark runner that pretty prints all of the taken measurements.
6914
/// Heavily inspired by [poop](https://github.com/andrewrk/poop/tree/main)
7015
pub fn BenchmarkRunner(

build/color.zig

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
const std = @import("std");
2+
3+
/// Minimal set of ansi color codes.
4+
pub const AnsiColorCodes = enum {
5+
black,
6+
red,
7+
green,
8+
yellow,
9+
blue,
10+
magenta,
11+
cyan,
12+
white,
13+
bright_black,
14+
bright_red,
15+
bright_green,
16+
bright_yellow,
17+
bright_blue,
18+
bright_magenta,
19+
bright_cyan,
20+
bright_white,
21+
reset,
22+
bold,
23+
dim,
24+
italic,
25+
underline,
26+
strikethrough,
27+
28+
/// Grabs the ansi escaped codes from the currently active one.
29+
pub fn toSlice(color: AnsiColorCodes) []const u8 {
30+
const color_string = switch (color) {
31+
.black => "\x1b[30m",
32+
.red => "\x1b[31m",
33+
.green => "\x1b[32m",
34+
.yellow => "\x1b[33m",
35+
.blue => "\x1b[34m",
36+
.magenta => "\x1b[35m",
37+
.cyan => "\x1b[36m",
38+
.white => "\x1b[37m",
39+
.bright_black => "\x1b[90m",
40+
.bright_red => "\x1b[91m",
41+
.bright_green => "\x1b[92m",
42+
.bright_yellow => "\x1b[93m",
43+
.bright_blue => "\x1b[94m",
44+
.bright_magenta => "\x1b[95m",
45+
.bright_cyan => "\x1b[96m",
46+
.bright_white => "\x1b[97m",
47+
.reset => "\x1b[0m",
48+
.bold => "\x1b[1m",
49+
.dim => "\x1b[2m",
50+
.italic => "\x1b[3m",
51+
.underline => "\x1b[4m",
52+
.strikethrough => "\x1b[9m",
53+
};
54+
55+
return color_string;
56+
}
57+
};
58+
59+
/// Custom writer that we use to write tests result and with specific tty colors.
60+
pub fn ColorWriter(comptime UnderlayingWriter: type) type {
61+
return struct {
62+
/// Set of possible errors from this writer.
63+
pub const Error = UnderlayingWriter.Error;
64+
65+
const Writer = std.io.Writer(*Self, Error, write);
66+
const Self = @This();
67+
68+
/// Initial empty state.
69+
pub const empty: Self = .{
70+
.color = .reset,
71+
.underlaying_writer = std.io.getStdErr().writer(),
72+
};
73+
74+
/// The writer that we will use to write to.
75+
underlaying_writer: UnderlayingWriter,
76+
/// Next tty color to apply in the stream.
77+
color: AnsiColorCodes,
78+
79+
pub fn writer(self: *Self) Writer {
80+
return .{ .context = self };
81+
}
82+
/// Write function that will write to the stream with the `next_color`.
83+
pub fn write(self: *Self, bytes: []const u8) Error!usize {
84+
if (bytes.len == 0)
85+
return bytes.len;
86+
87+
try self.applyColor();
88+
try self.writeNoColor(bytes);
89+
try self.applyReset();
90+
91+
return bytes.len;
92+
}
93+
/// Sets the next color in the stream
94+
pub fn setNextColor(self: *Self, next: AnsiColorCodes) void {
95+
self.color = next;
96+
}
97+
/// Writes the next color to the stream.
98+
pub fn applyColor(self: *Self) Error!void {
99+
try self.underlaying_writer.writeAll(self.color.toSlice());
100+
}
101+
/// Writes the reset ansi to the stream
102+
pub fn applyReset(self: *Self) Error!void {
103+
try self.underlaying_writer.writeAll(AnsiColorCodes.toSlice(.reset));
104+
}
105+
/// Writes to the stream without colors.
106+
pub fn writeNoColor(self: *Self, bytes: []const u8) UnderlayingWriter.Error!void {
107+
if (bytes.len == 0)
108+
return;
109+
110+
try self.underlaying_writer.writeAll(bytes);
111+
}
112+
};
113+
}

build/test_runner.zig

Lines changed: 30 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
const builtin = @import("builtin");
2+
const color = @import("color.zig");
23
const std = @import("std");
34

45
const Allocator = std.mem.Allocator;
56
const Anvil = @import("zabi").clients.Anvil;
7+
const ColorWriter = color.ColorWriter;
68
const FileWriter = std.fs.File.Writer;
79
const Options = std.Options;
8-
const TerminalColors = std.io.tty.Color;
910
const TestFn = std.builtin.TestFn;
10-
const ZigColor = std.zig.Color;
1111

1212
pub const std_options: Options = .{
1313
.log_level = .info,
@@ -52,11 +52,18 @@ const Runner = struct {
5252
}
5353
/// Writes the test module name.
5454
pub fn writeModule(self: *Self, module: []const u8) ColorWriterStream.Error!void {
55-
try self.color_stream.writeModule(module);
55+
self.color_stream.setNextColor(.yellow);
56+
try self.color_stream.writer().print(" |{s}|", .{module});
57+
try self.color_stream.applyReset();
5658
}
5759
/// Writes the test name.
5860
pub fn writeTestName(self: *Self, name: []const u8) ColorWriterStream.Error!void {
59-
try self.color_stream.writeTestName(name);
61+
self.color_stream.setNextColor(.dim);
62+
63+
const index = std.mem.lastIndexOf(u8, name, "test.") orelse unreachable;
64+
65+
try self.color_stream.writer().print(" Running {s}...", .{name[index + 5 ..]});
66+
try self.color_stream.applyReset();
6067
}
6168
/// Write a success result to the stream
6269
pub fn writeSuccess(self: *Self) ColorWriterStream.Error!void {
@@ -88,100 +95,28 @@ const Runner = struct {
8895
}
8996
/// Pretty print the test results.
9097
pub fn writeResult(self: *Self) ColorWriterStream.Error!void {
91-
try self.color_stream.printResult(self.result);
92-
}
93-
};
94-
95-
/// Custom writer that we use to write tests result and with specific tty colors.
96-
fn ColorWriter(comptime UnderlayingWriter: type) type {
97-
return struct {
98-
/// Set of possible errors from this writer.
99-
const Error = UnderlayingWriter.Error || std.os.windows.SetConsoleTextAttributeError;
100-
101-
const Writer = std.io.Writer(*Self, Error, write);
102-
const Self = @This();
103-
104-
/// Initial empty state.
105-
pub const empty: Self = .{
106-
.color = .auto,
107-
.underlaying_writer = std.io.getStdErr().writer(),
108-
.next_color = .reset,
109-
};
110-
111-
/// The writer that we will use to write to.
112-
underlaying_writer: UnderlayingWriter,
113-
/// Zig color tty config.
114-
color: ZigColor,
115-
/// Next tty color to apply in the stream.
116-
next_color: TerminalColors,
117-
118-
pub fn writer(self: *Self) Writer {
119-
return .{ .context = self };
120-
}
121-
/// Write function that will write to the stream with the `next_color`.
122-
pub fn write(self: *Self, bytes: []const u8) Error!usize {
123-
if (bytes.len == 0)
124-
return bytes.len;
98+
self.color_stream.setNextColor(.reset);
99+
try self.color_stream.writer().writeAll("\n ZABI Tests: ");
100+
self.color_stream.setNextColor(.green);
101+
try self.color_stream.writer().print("{d} passed\n", .{self.result.passed});
102+
self.color_stream.setNextColor(.reset);
125103

126-
try self.applyColor(self.next_color);
127-
try self.writeNoColor(bytes);
128-
try self.applyColor(.reset);
104+
try self.color_stream.writer().writeAll(" ZABI Tests: ");
105+
self.color_stream.setNextColor(.red);
106+
try self.color_stream.writer().print("{d} failed\n", .{self.result.failed});
107+
self.color_stream.setNextColor(.reset);
129108

130-
return bytes.len;
131-
}
132-
/// Writes the test module to the stream.
133-
pub fn writeModule(self: *Self, module: []const u8) !void {
134-
self.setNextColor(.yellow);
135-
try self.applyColor(self.next_color);
136-
try self.underlaying_writer.print(" |{s}|", .{module});
137-
try self.applyColor(.reset);
138-
}
139-
/// Writes the test name with ansi `dim`.
140-
pub fn writeTestName(self: *Self, test_name: []const u8) !void {
141-
self.setNextColor(.dim);
142-
try self.applyColor(self.next_color);
143-
try self.underlaying_writer.print(" Running {s}...", .{test_name});
144-
try self.applyColor(.reset);
145-
}
146-
/// Sets the next color in the stream
147-
pub fn setNextColor(self: *Self, next: TerminalColors) void {
148-
self.next_color = next;
149-
}
150-
/// Writes the next color to the stream.
151-
pub fn applyColor(self: *Self, color: TerminalColors) Error!void {
152-
try self.color.renderOptions().ttyconf.setColor(self.underlaying_writer, color);
153-
}
154-
/// Writes to the stream without colors.
155-
pub fn writeNoColor(self: *Self, bytes: []const u8) UnderlayingWriter.Error!void {
156-
if (bytes.len == 0)
157-
return;
109+
try self.color_stream.writer().writeAll(" ZABI Tests: ");
110+
self.color_stream.setNextColor(.yellow);
111+
try self.color_stream.writer().print("{d} skipped\n", .{self.result.skipped});
112+
self.color_stream.setNextColor(.reset);
158113

159-
try self.underlaying_writer.writeAll(bytes);
160-
}
161-
/// Prints all of the test results.
162-
pub fn printResult(self: *Self, results: TestResults) Error!void {
163-
try self.underlaying_writer.writeAll("\n ZABI Tests: ");
164-
try self.applyColor(.green);
165-
try self.underlaying_writer.print("{d} passed\n", .{results.passed});
166-
try self.applyColor(.reset);
167-
168-
try self.underlaying_writer.writeAll(" ZABI Tests: ");
169-
try self.applyColor(.red);
170-
try self.underlaying_writer.print("{d} failed\n", .{results.failed});
171-
try self.applyColor(.reset);
172-
173-
try self.underlaying_writer.writeAll(" ZABI Tests: ");
174-
try self.applyColor(.yellow);
175-
try self.underlaying_writer.print("{d} skipped\n", .{results.skipped});
176-
try self.applyColor(.reset);
177-
178-
try self.underlaying_writer.writeAll(" ZABI Tests: ");
179-
try self.applyColor(.blue);
180-
try self.underlaying_writer.print("{d} leaked\n", .{results.leaked});
181-
try self.applyColor(.reset);
182-
}
183-
};
184-
}
114+
try self.color_stream.writer().writeAll(" ZABI Tests: ");
115+
self.color_stream.setNextColor(.blue);
116+
try self.color_stream.writer().print("{d} leaked\n", .{self.result.leaked});
117+
self.color_stream.setNextColor(.reset);
118+
}
119+
};
185120

186121
/// Main test runner.
187122
pub fn main() !void {

0 commit comments

Comments
 (0)