tangled
alpha
login
or
join now
altagos.dev
/
pretty
0
fork
atom
A pretty printer for zig
zig
0
fork
atom
overview
issues
pulls
pipelines
pretty printing for primitive types
altagos.dev
1 month ago
94f031c1
d3a0edca
verified
This commit was signed with the committer's
known signature
.
altagos.dev
SSH Key Fingerprint:
SHA256:UbTjEcCZlc6GzQWLCuDK3D//HESWD2xFPkzue9XMras=
+210
2 changed files
expand all
collapse all
unified
split
example
main.zig
pretty.zig
+48
example/main.zig
···
1
1
+
const std = @import("std");
2
2
+
const print = std.debug.print;
3
3
+
4
4
+
const pretty_mod = @import("pretty");
5
5
+
const pretty = pretty_mod.pretty;
6
6
+
const Pretty = pretty_mod.PrettyWithOptions;
7
7
+
8
8
+
const Hello = enum { world };
9
9
+
10
10
+
pub fn main(init: std.process.Init) !void {
11
11
+
_ = init;
12
12
+
13
13
+
print("Booleans\n", .{});
14
14
+
print("Boolean true - {f}\n", .{pretty(true)});
15
15
+
print(
16
16
+
"Boolean false - {f}\n",
17
17
+
.{Pretty(bool, .{ .show_type_names = false, .type_value_seperator = "" }).init(false)},
18
18
+
);
19
19
+
print(
20
20
+
"Boolean true with type name - {f}\n",
21
21
+
.{Pretty(bool, .{ .always_show_type_names = true, .type_value_seperator = ": " }).init(true)},
22
22
+
);
23
23
+
24
24
+
print("\nUnsigned Integers\n", .{});
25
25
+
print("Pretty u8 - {f}\n", .{pretty(@as(u8, 42))});
26
26
+
print("Pretty u16 - {f}\n", .{pretty(@as(u16, 42))});
27
27
+
print("Pretty u32 - {f}\n", .{pretty(@as(u32, 42))});
28
28
+
print("Pretty u64 - {f}\n", .{pretty(@as(u64, 42))});
29
29
+
print("Pretty usize - {f}\n", .{pretty(@as(usize, 42))});
30
30
+
31
31
+
print("\nSigned Integers\n", .{});
32
32
+
print("Pretty comptime_int - {f}\n", .{pretty(42)});
33
33
+
print("Pretty i8 - {f}\n", .{pretty(@as(i8, 42))});
34
34
+
print("Pretty i16 - {f}\n", .{pretty(@as(i16, 42))});
35
35
+
print("Pretty i32 - {f}\n", .{pretty(@as(i32, 42))});
36
36
+
print("Pretty i64 - {f}\n", .{pretty(@as(i64, 42))});
37
37
+
print("Pretty isize - {f}\n", .{pretty(@as(isize, 42))});
38
38
+
39
39
+
print("\nFloats\n", .{});
40
40
+
print("Pretty comptime_float - {f}\n", .{pretty(3.131)});
41
41
+
print("Pretty f16 - {f}\n", .{pretty(@as(f16, 3.141))});
42
42
+
print("Pretty f32 - {f}\n", .{pretty(@as(f32, 3.141))});
43
43
+
print("Pretty f64 - {f}\n", .{pretty(@as(f64, 3.141))});
44
44
+
45
45
+
print("\nEnums\n", .{});
46
46
+
print("Pretty enum - {f}\n", .{pretty(Hello.world)});
47
47
+
print("Pretty enum literal - {f}\n", .{pretty(.hello_world)});
48
48
+
}
+162
pretty.zig
···
1
1
+
const std = @import("std");
2
2
+
const Io = std.Io;
3
3
+
4
4
+
pub const Options = struct {
5
5
+
indent_width: comptime_int = 2,
6
6
+
7
7
+
show_type_names: bool = true,
8
8
+
always_show_type_names: bool = true,
9
9
+
10
10
+
type_value_seperator: []const u8 = " = ",
11
11
+
};
12
12
+
13
13
+
pub fn pretty(value: anytype) Pretty(@TypeOf(value)) {
14
14
+
return Pretty(@TypeOf(value)).init(value);
15
15
+
}
16
16
+
17
17
+
pub fn Pretty(comptime T: type) type {
18
18
+
return PrettyWithOptions(T, .{});
19
19
+
}
20
20
+
21
21
+
pub fn PrettyWithOptions(comptime T: type, comptime options: Options) type {
22
22
+
const global = struct {
23
23
+
var tty: ?Io.Terminal = null;
24
24
+
};
25
25
+
26
26
+
return struct {
27
27
+
value: T,
28
28
+
29
29
+
pub fn init(val: T) @This() {
30
30
+
return .{ .value = val };
31
31
+
}
32
32
+
33
33
+
pub fn format(this: *const @This(), w: *std.Io.Writer) error{WriteFailed}!void {
34
34
+
if (global.tty == null) {
35
35
+
var buffer: [1]u8 = undefined;
36
36
+
const stderr = std.debug.lockStderr(&buffer).terminal();
37
37
+
defer std.debug.unlockStderr();
38
38
+
39
39
+
global.tty = stderr;
40
40
+
global.tty.?.writer = w;
41
41
+
}
42
42
+
43
43
+
const comp_ctx = ComptimeContext{ .options = options };
44
44
+
const run_ctx = RuntimeContext{
45
45
+
.out = w,
46
46
+
.tty = global.tty.?,
47
47
+
};
48
48
+
49
49
+
return innerFmt(T, comp_ctx, this.value, run_ctx);
50
50
+
}
51
51
+
};
52
52
+
}
53
53
+
54
54
+
const RuntimeContext = struct {
55
55
+
out: *Io.Writer,
56
56
+
tty: Io.Terminal,
57
57
+
58
58
+
depth: usize = 0,
59
59
+
60
60
+
indent_level: usize = 0,
61
61
+
62
62
+
pub fn print(this: RuntimeContext, comptime fmt: []const u8, args: anytype) error{WriteFailed}!void {
63
63
+
return this.out.print(fmt, args);
64
64
+
}
65
65
+
66
66
+
pub fn setColor(this: RuntimeContext, color: Io.Terminal.Color) void {
67
67
+
this.tty.setColor(color) catch {};
68
68
+
}
69
69
+
70
70
+
pub fn resetColor(this: RuntimeContext) void {
71
71
+
this.tty.setColor(.reset) catch {};
72
72
+
}
73
73
+
};
74
74
+
75
75
+
const ComptimeContext = struct {
76
76
+
depth: comptime_int = 0,
77
77
+
78
78
+
indent_level: comptime_int = 0,
79
79
+
80
80
+
options: Options,
81
81
+
exited_comptime: bool = false,
82
82
+
83
83
+
pub fn inComptime(comptime this: ComptimeContext) bool {
84
84
+
if (!this.exited_comptime) return false;
85
85
+
return @inComptime();
86
86
+
}
87
87
+
};
88
88
+
89
89
+
fn innerFmt(
90
90
+
comptime T: type,
91
91
+
comptime cctx: ComptimeContext,
92
92
+
value: T,
93
93
+
rctx: RuntimeContext,
94
94
+
) error{WriteFailed}!void {
95
95
+
const info = @typeInfo(T);
96
96
+
try printType(T, cctx, rctx, info);
97
97
+
98
98
+
return switch (info) {
99
99
+
.bool => formatBool(rctx, value),
100
100
+
101
101
+
.comptime_int,
102
102
+
.comptime_float,
103
103
+
.int,
104
104
+
.float,
105
105
+
.@"enum",
106
106
+
.enum_literal,
107
107
+
=> formatValue(rctx, value),
108
108
+
109
109
+
else => {
110
110
+
rctx.setColor(.red);
111
111
+
try rctx.print("Unimplemented! ({} = {any})", .{ info, value });
112
112
+
rctx.resetColor();
113
113
+
},
114
114
+
};
115
115
+
}
116
116
+
117
117
+
inline fn printType(
118
118
+
comptime T: type,
119
119
+
comptime cctx: ComptimeContext,
120
120
+
rctx: RuntimeContext,
121
121
+
comptime info: std.builtin.Type,
122
122
+
) error{WriteFailed}!void {
123
123
+
if (cctx.depth != 0 or cctx.options.always_show_type_names) {
124
124
+
rctx.setColor(.dim);
125
125
+
126
126
+
if (cctx.options.show_type_names) {
127
127
+
switch (info) {
128
128
+
.bool => try rctx.print("bool{s}", .{cctx.options.type_value_seperator}),
129
129
+
.comptime_int => try rctx.print("comptime_int{s}", .{cctx.options.type_value_seperator}),
130
130
+
.comptime_float => try rctx.print("comptime_float{s}", .{cctx.options.type_value_seperator}),
131
131
+
.int => |int| try rctx.print(
132
132
+
"{s}{}{s}",
133
133
+
.{
134
134
+
if (int.signedness == .signed) "i" else "u",
135
135
+
int.bits,
136
136
+
cctx.options.type_value_seperator,
137
137
+
},
138
138
+
),
139
139
+
.float => |float| try rctx.print("f{}{s}", .{ float.bits, cctx.options.type_value_seperator }),
140
140
+
.enum_literal => try rctx.print("enum literal{s}", .{cctx.options.type_value_seperator}),
141
141
+
.@"enum" => try rctx.print("{s}{s}", .{ @typeName(T), cctx.options.type_value_seperator }),
142
142
+
else => try rctx.print("missing {}{s}", .{ info, cctx.options.type_value_seperator }),
143
143
+
}
144
144
+
} else {
145
145
+
try rctx.print("{s}", .{cctx.options.type_value_seperator});
146
146
+
}
147
147
+
148
148
+
rctx.resetColor();
149
149
+
}
150
150
+
}
151
151
+
152
152
+
inline fn formatBool(rctx: RuntimeContext, value: bool) !void {
153
153
+
rctx.setColor(if (value) .bright_green else .bright_red);
154
154
+
try rctx.print("{}", .{value});
155
155
+
rctx.resetColor();
156
156
+
}
157
157
+
158
158
+
inline fn formatValue(rctx: RuntimeContext, value: anytype) !void {
159
159
+
rctx.setColor(.blue);
160
160
+
try rctx.print("{}", .{value});
161
161
+
rctx.resetColor();
162
162
+
}