tangled
alpha
login
or
join now
altagos.dev
/
space
0
fork
atom
A SpaceTraders Agent
0
fork
atom
overview
issues
pulls
pipelines
create custom pretty printer
altagos.dev
3 months ago
0a2b039f
960c034f
verified
This commit was signed with the committer's
known signature
.
altagos.dev
SSH Key Fingerprint:
SHA256:UbTjEcCZlc6GzQWLCuDK3D//HESWD2xFPkzue9XMras=
+465
3 changed files
expand all
collapse all
unified
split
build.zig
src
meta
fmt.zig
root.zig
+9
build.zig
···
7
7
const options = b.addOptions();
8
8
9
9
const known_folders = b.dependency("known_folders", .{}).module("known-folders");
10
10
+
11
11
+
const meta = b.createModule(.{
12
12
+
.root_source_file = b.path("src/meta/root.zig"),
13
13
+
.target = target,
14
14
+
.optimize = optimize,
15
15
+
});
16
16
+
10
17
const st = b.addModule("st", .{
11
18
.root_source_file = b.path("src/st/root.zig"),
12
19
.target = target,
···
31
38
.optimize = optimize,
32
39
.imports = &.{
33
40
.{ .name = "known-folders", .module = known_folders },
41
41
+
// Modules
34
42
.{ .name = "st", .module = st },
35
43
.{ .name = "agent", .module = agent },
44
44
+
.{ .name = "meta", .module = meta },
36
45
},
37
46
});
38
47
+453
src/meta/fmt.zig
···
1
1
+
const std = @import("std");
2
2
+
const Io = std.Io;
3
3
+
const Type = std.builtin.Type;
4
4
+
5
5
+
pub fn pretty(value: anytype) Pretty(@TypeOf(value)) {
6
6
+
return Pretty(@TypeOf(value)).init(value);
7
7
+
}
8
8
+
9
9
+
fn Context(comptime runtime: bool) type {
10
10
+
if (runtime) {
11
11
+
return struct {
12
12
+
indent_width: u8 = 2,
13
13
+
indent_level: usize = 0,
14
14
+
};
15
15
+
} else {
16
16
+
return struct {
17
17
+
indent_width: comptime_int = 2,
18
18
+
indent_level: comptime_int = 0,
19
19
+
};
20
20
+
}
21
21
+
}
22
22
+
23
23
+
const Options = struct {
24
24
+
type_name: bool = true,
25
25
+
last_layer_type_name: bool = true,
26
26
+
27
27
+
follow_pointers: bool = true,
28
28
+
};
29
29
+
30
30
+
pub fn Pretty(comptime T: type) type {
31
31
+
const global = struct {
32
32
+
var conf: ?std.Io.tty.Config = null;
33
33
+
};
34
34
+
return struct {
35
35
+
value: T,
36
36
+
pub fn init(val: T) @This() {
37
37
+
return .{ .value = val };
38
38
+
}
39
39
+
pub fn format(this: *const @This(), w: *std.Io.Writer) error{WriteFailed}!void {
40
40
+
if (global.conf == null) {
41
41
+
global.conf = .detect(.stderr());
42
42
+
}
43
43
+
return innerFmt(w, global.conf.?, T, this.value, false, .{}, .{});
44
44
+
}
45
45
+
};
46
46
+
}
47
47
+
48
48
+
const Color = enum {
49
49
+
dim,
50
50
+
reset,
51
51
+
text,
52
52
+
field,
53
53
+
value,
54
54
+
};
55
55
+
56
56
+
fn setColor(
57
57
+
w: *Io.Writer,
58
58
+
tty: Io.tty.Config,
59
59
+
color: Color,
60
60
+
) void {
61
61
+
switch (color) {
62
62
+
.dim => {
63
63
+
tty.setColor(w, .dim) catch {};
64
64
+
},
65
65
+
.reset => {
66
66
+
tty.setColor(w, .reset) catch {};
67
67
+
},
68
68
+
.text => {
69
69
+
tty.setColor(w, .italic) catch {};
70
70
+
tty.setColor(w, .dim) catch {};
71
71
+
tty.setColor(w, .blue) catch {};
72
72
+
},
73
73
+
.field => {
74
74
+
tty.setColor(w, .green) catch {};
75
75
+
},
76
76
+
.value => {
77
77
+
tty.setColor(w, .italic) catch {};
78
78
+
tty.setColor(w, .blue) catch {};
79
79
+
},
80
80
+
}
81
81
+
}
82
82
+
83
83
+
fn innerFmt(
84
84
+
w: *std.Io.Writer,
85
85
+
tty: std.Io.tty.Config,
86
86
+
comptime T: type,
87
87
+
value: T,
88
88
+
comptime runtime: bool,
89
89
+
ctx: Context(runtime),
90
90
+
opts: Options,
91
91
+
) error{WriteFailed}!void {
92
92
+
const info = @typeInfo(T);
93
93
+
94
94
+
switch (info) {
95
95
+
.bool => try printBool(w, tty, value, opts),
96
96
+
.int => |int| try printInt(w, tty, int, value, opts),
97
97
+
.float => |float| try printFloat(w, tty, float, value, opts),
98
98
+
.@"enum", .enum_literal => try printEnum(w, tty, value, opts),
99
99
+
.optional => |optional| try printOptional(w, tty, optional, value, runtime, ctx, opts),
100
100
+
.pointer => |ptr| {
101
101
+
if (opts.follow_pointers) {
102
102
+
try printPointer(w, tty, ptr, value, runtime, ctx, opts);
103
103
+
} else {}
104
104
+
},
105
105
+
.array => |array| try printArray(w, tty, array, value, runtime, ctx, opts),
106
106
+
.@"struct" => |str| try printStruct(T, w, tty, str, value, runtime, ctx, opts),
107
107
+
else => {
108
108
+
tty.setColor(w, .red) catch {};
109
109
+
try w.print("Unimplemented! ({})", .{info});
110
110
+
setColor(w, tty, .reset);
111
111
+
},
112
112
+
}
113
113
+
}
114
114
+
115
115
+
fn printBool(
116
116
+
w: *Io.Writer,
117
117
+
tty: Io.tty.Config,
118
118
+
value: bool,
119
119
+
opts: Options,
120
120
+
) !void {
121
121
+
if (opts.type_name) {
122
122
+
setColor(w, tty, .dim);
123
123
+
try w.print("bool => ", .{});
124
124
+
setColor(w, tty, .reset);
125
125
+
} else {
126
126
+
tty.setColor(w, .dim) catch {};
127
127
+
try w.print("=> ", .{});
128
128
+
setColor(w, tty, .reset);
129
129
+
}
130
130
+
setColor(w, tty, .value);
131
131
+
if (value) {
132
132
+
tty.setColor(w, .bright_green) catch {};
133
133
+
} else {
134
134
+
tty.setColor(w, .bright_red) catch {};
135
135
+
}
136
136
+
try w.print("{}", .{value});
137
137
+
setColor(w, tty, .reset);
138
138
+
}
139
139
+
140
140
+
fn printInt(
141
141
+
w: *Io.Writer,
142
142
+
tty: Io.tty.Config,
143
143
+
int: Type.Int,
144
144
+
value: anytype,
145
145
+
opts: Options,
146
146
+
) !void {
147
147
+
if (opts.type_name) {
148
148
+
tty.setColor(w, .dim) catch {};
149
149
+
try w.print("{s}{} => ", .{ if (int.signedness == .signed) "i" else "u", int.bits });
150
150
+
setColor(w, tty, .reset);
151
151
+
} else {
152
152
+
tty.setColor(w, .dim) catch {};
153
153
+
try w.print("=> ", .{});
154
154
+
setColor(w, tty, .reset);
155
155
+
}
156
156
+
setColor(w, tty, .value);
157
157
+
try w.print("{}", .{value});
158
158
+
setColor(w, tty, .reset);
159
159
+
}
160
160
+
161
161
+
fn printFloat(
162
162
+
w: *Io.Writer,
163
163
+
tty: Io.tty.Config,
164
164
+
float: Type.Float,
165
165
+
value: anytype,
166
166
+
opts: Options,
167
167
+
) !void {
168
168
+
if (opts.type_name) {
169
169
+
tty.setColor(w, .dim) catch {};
170
170
+
try w.print("f{} => ", .{float.bits});
171
171
+
setColor(w, tty, .reset);
172
172
+
} else {
173
173
+
tty.setColor(w, .dim) catch {};
174
174
+
try w.print("=> ", .{});
175
175
+
setColor(w, tty, .reset);
176
176
+
}
177
177
+
setColor(w, tty, .value);
178
178
+
try w.print("{}", .{value});
179
179
+
setColor(w, tty, .reset);
180
180
+
}
181
181
+
182
182
+
fn printEnum(
183
183
+
w: *Io.Writer,
184
184
+
tty: Io.tty.Config,
185
185
+
value: anytype,
186
186
+
opts: Options,
187
187
+
) !void {
188
188
+
if (opts.type_name) {
189
189
+
tty.setColor(w, .dim) catch {};
190
190
+
try w.print("{s} => ", .{@typeName(@TypeOf(value))});
191
191
+
setColor(w, tty, .reset);
192
192
+
} else {
193
193
+
tty.setColor(w, .dim) catch {};
194
194
+
try w.print("=> ", .{});
195
195
+
setColor(w, tty, .reset);
196
196
+
}
197
197
+
setColor(w, tty, .value);
198
198
+
try w.print("{}", .{value});
199
199
+
setColor(w, tty, .reset);
200
200
+
}
201
201
+
202
202
+
fn printOptional(
203
203
+
w: *Io.Writer,
204
204
+
tty: Io.tty.Config,
205
205
+
optional: Type.Optional,
206
206
+
value: anytype,
207
207
+
comptime runtime: bool,
208
208
+
ctx: Context(runtime),
209
209
+
opts: Options,
210
210
+
) !void {
211
211
+
var next_opts = opts;
212
212
+
next_opts.type_name = if (!opts.type_name and !opts.last_layer_type_name) false else true;
213
213
+
next_opts.last_layer_type_name = opts.type_name;
214
214
+
215
215
+
if (opts.type_name) {
216
216
+
tty.setColor(w, .dim) catch {};
217
217
+
try w.print("?", .{});
218
218
+
setColor(w, tty, .reset);
219
219
+
}
220
220
+
221
221
+
if (value) |val| {
222
222
+
try innerFmt(w, tty, optional.child, val, runtime, ctx, next_opts);
223
223
+
} else {
224
224
+
if (opts.type_name) {
225
225
+
tty.setColor(w, .dim) catch {};
226
226
+
try w.print("{s} => ", .{@typeName(optional.child)});
227
227
+
setColor(w, tty, .reset);
228
228
+
} else {
229
229
+
tty.setColor(w, .dim) catch {};
230
230
+
try w.print("=> ", .{});
231
231
+
setColor(w, tty, .reset);
232
232
+
}
233
233
+
234
234
+
tty.setColor(w, .blue) catch {};
235
235
+
try w.writeAll("null");
236
236
+
setColor(w, tty, .reset);
237
237
+
}
238
238
+
}
239
239
+
240
240
+
fn printArray(
241
241
+
w: *Io.Writer,
242
242
+
tty: Io.tty.Config,
243
243
+
array: Type.Array,
244
244
+
value: anytype,
245
245
+
comptime runtime: bool,
246
246
+
ctx: Context(runtime),
247
247
+
opts: Options,
248
248
+
) !void {
249
249
+
comptime var next_ctx = ctx;
250
250
+
251
251
+
var next_opts = opts;
252
252
+
next_opts.type_name = if (!opts.type_name and !opts.last_layer_type_name) false else true;
253
253
+
next_opts.last_layer_type_name = opts.type_name;
254
254
+
255
255
+
if (opts.type_name) {
256
256
+
tty.setColor(w, .dim) catch {};
257
257
+
try w.print("[{}]{s} =>", .{ array.len, @typeName(array.child) });
258
258
+
setColor(w, tty, .reset);
259
259
+
} else {
260
260
+
tty.setColor(w, .dim) catch {};
261
261
+
try w.print("=> ", .{});
262
262
+
setColor(w, tty, .reset);
263
263
+
}
264
264
+
265
265
+
inline for (value, 0..) |item, idx| {
266
266
+
try indent(w, runtime, ctx);
267
267
+
268
268
+
setColor(w, tty, .field);
269
269
+
try w.print("[{}] ", .{idx});
270
270
+
setColor(w, tty, .reset);
271
271
+
272
272
+
next_ctx.indent_level = ctx.indent_level + 1;
273
273
+
next_opts.type_name = false;
274
274
+
275
275
+
try innerFmt(w, tty, @TypeOf(item), item, runtime, next_ctx, next_opts);
276
276
+
}
277
277
+
}
278
278
+
279
279
+
fn printPointer(
280
280
+
w: *Io.Writer,
281
281
+
tty: Io.tty.Config,
282
282
+
ptr: Type.Pointer,
283
283
+
value: anytype,
284
284
+
comptime runtime: bool,
285
285
+
ctx: Context(runtime),
286
286
+
opts: Options,
287
287
+
) !void {
288
288
+
var next_opts = opts;
289
289
+
next_opts.type_name = if (!opts.type_name and !opts.last_layer_type_name) false else true;
290
290
+
next_opts.last_layer_type_name = opts.type_name;
291
291
+
292
292
+
switch (ptr.size) {
293
293
+
.one => {
294
294
+
if (opts.type_name) {
295
295
+
tty.setColor(w, .dim) catch {};
296
296
+
try w.print("*{s}", .{if (ptr.is_const) "const " else ""});
297
297
+
setColor(w, tty, .reset);
298
298
+
}
299
299
+
300
300
+
if (ptr.child == anyopaque or @typeInfo(ptr.child) == .@"fn")
301
301
+
return;
302
302
+
303
303
+
try innerFmt(w, tty, ptr.child, value, runtime, ctx, next_opts);
304
304
+
},
305
305
+
.slice => {
306
306
+
if (opts.type_name) {
307
307
+
setColor(w, tty, .dim);
308
308
+
try w.print("[]{s}", .{if (ptr.is_const) "const " else ""});
309
309
+
setColor(w, tty, .reset);
310
310
+
}
311
311
+
312
312
+
if (ptr.child == u8) {
313
313
+
tty.setColor(w, .dim) catch {};
314
314
+
try w.print("{s}=>", .{if (opts.type_name) "u8 " else ""});
315
315
+
setColor(w, tty, .reset);
316
316
+
317
317
+
try indent(w, runtime, ctx);
318
318
+
319
319
+
setColor(w, tty, .text);
320
320
+
try w.print("\"{s}\"", .{value});
321
321
+
setColor(w, tty, .reset);
322
322
+
return;
323
323
+
}
324
324
+
325
325
+
setColor(w, tty, .dim);
326
326
+
try w.print("{s}{s}", .{
327
327
+
if (opts.type_name) @typeName(ptr.child) else "",
328
328
+
if (opts.type_name) " =>" else "=>",
329
329
+
});
330
330
+
setColor(w, tty, .reset);
331
331
+
332
332
+
const run_ctx: Context(true) = .{ .indent_width = ctx.indent_width, .indent_level = ctx.indent_level };
333
333
+
var next_ctx: Context(true) = .{ .indent_width = ctx.indent_width, .indent_level = ctx.indent_level };
334
334
+
335
335
+
var count: usize = 0;
336
336
+
for (value, 0..) |item, idx| {
337
337
+
try indent(w, true, run_ctx);
338
338
+
339
339
+
setColor(w, tty, .field);
340
340
+
try w.print("[{}] ", .{idx});
341
341
+
setColor(w, tty, .reset);
342
342
+
343
343
+
next_ctx.indent_level = ctx.indent_level + 1;
344
344
+
next_opts.type_name = false;
345
345
+
346
346
+
try innerFmt(w, tty, @TypeOf(item), item, true, next_ctx, next_opts);
347
347
+
count += 1;
348
348
+
}
349
349
+
350
350
+
if (count == 0) {
351
351
+
setColor(w, tty, .dim);
352
352
+
try w.writeAll(" empty");
353
353
+
setColor(w, tty, .reset);
354
354
+
}
355
355
+
},
356
356
+
else => {
357
357
+
try w.print("unimplemented {}", .{ptr});
358
358
+
},
359
359
+
}
360
360
+
}
361
361
+
362
362
+
fn printStruct(
363
363
+
comptime T: type,
364
364
+
w: *Io.Writer,
365
365
+
tty: Io.tty.Config,
366
366
+
str: Type.Struct,
367
367
+
value: anytype,
368
368
+
comptime runtime: bool,
369
369
+
ctx: Context(runtime),
370
370
+
opts: Options,
371
371
+
) !void {
372
372
+
var next_opts = opts;
373
373
+
next_opts.type_name = if (!opts.type_name and !opts.last_layer_type_name) false else true;
374
374
+
next_opts.last_layer_type_name = opts.type_name;
375
375
+
376
376
+
setColor(w, tty, .dim);
377
377
+
if (opts.type_name) {
378
378
+
try w.print("{s} =>", .{@typeName(T)});
379
379
+
} else {
380
380
+
try w.print("=>", .{});
381
381
+
}
382
382
+
setColor(w, tty, .reset);
383
383
+
384
384
+
if (runtime) {
385
385
+
var next_ctx: Context(true) = ctx;
386
386
+
387
387
+
inline for (str.fields) |field| {
388
388
+
try indent(w, runtime, ctx);
389
389
+
390
390
+
setColor(w, tty, .field);
391
391
+
try w.print(".{s}", .{field.name});
392
392
+
setColor(w, tty, .reset);
393
393
+
394
394
+
setColor(w, tty, .dim);
395
395
+
if (opts.type_name) {
396
396
+
try w.writeAll(": ");
397
397
+
} else try w.writeByte(' ');
398
398
+
setColor(w, tty, .reset);
399
399
+
400
400
+
next_ctx.indent_level = ctx.indent_level + 1;
401
401
+
402
402
+
try innerFmt(
403
403
+
w,
404
404
+
tty,
405
405
+
field.type,
406
406
+
@field(value, field.name),
407
407
+
runtime,
408
408
+
next_ctx,
409
409
+
next_opts,
410
410
+
);
411
411
+
}
412
412
+
} else {
413
413
+
comptime var next_ctx: Context(false) = ctx;
414
414
+
415
415
+
inline for (str.fields) |field| {
416
416
+
try indent(w, runtime, ctx);
417
417
+
418
418
+
setColor(w, tty, .field);
419
419
+
try w.print(".{s}", .{field.name});
420
420
+
setColor(w, tty, .reset);
421
421
+
422
422
+
setColor(w, tty, .dim);
423
423
+
if (opts.type_name) {
424
424
+
try w.writeAll(": ");
425
425
+
} else try w.writeByte(' ');
426
426
+
setColor(w, tty, .reset);
427
427
+
428
428
+
next_ctx.indent_level = ctx.indent_level + 1;
429
429
+
430
430
+
try innerFmt(
431
431
+
w,
432
432
+
tty,
433
433
+
field.type,
434
434
+
@field(value, field.name),
435
435
+
runtime,
436
436
+
next_ctx,
437
437
+
next_opts,
438
438
+
);
439
439
+
}
440
440
+
}
441
441
+
}
442
442
+
443
443
+
fn indent(w: *Io.Writer, comptime runtime: bool, ctx: Context(runtime)) !void {
444
444
+
try w.writeByte('\n');
445
445
+
if (runtime) {
446
446
+
for (0..((ctx.indent_level + 1) * ctx.indent_width)) |_| {
447
447
+
try w.writeByte(' ');
448
448
+
}
449
449
+
} else {
450
450
+
const text: [(ctx.indent_level + 1) * ctx.indent_width]u8 = @splat(' ');
451
451
+
try w.writeAll(&text);
452
452
+
}
453
453
+
}
+3
src/meta/root.zig
···
1
1
+
pub const fmt = @import("fmt.zig");
2
2
+
3
3
+
pub const pretty = fmt.pretty;