mod(zlog): pretty printing for user defined types
This commit is contained in:
74
src/zlog.zig
74
src/zlog.zig
@@ -1,7 +1,5 @@
|
||||
const std = @import("std");
|
||||
|
||||
const max_depth = 5;
|
||||
|
||||
// pub fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void
|
||||
// TODO: provide comptime helper function to add format function for user types:
|
||||
// - pretty printing
|
||||
@@ -30,7 +28,7 @@ fn logFn(
|
||||
// - should there be spacing?
|
||||
// - should the messages be aligned (left, center, right)?
|
||||
const level_txt = comptime message_level.asText();
|
||||
const prefix2 = if (scope == .default) ":\t" else "(" ++ @tagName(scope) ++ "):\t";
|
||||
const prefix = if (scope == .default) ":\t" else "(" ++ @tagName(scope) ++ "):\t";
|
||||
const stderr = std.io.getStdErr().writer();
|
||||
var bw = std.io.bufferedWriter(stderr);
|
||||
const writer = bw.writer();
|
||||
@@ -38,51 +36,65 @@ fn logFn(
|
||||
std.debug.lockStdErr();
|
||||
defer std.debug.unlockStdErr();
|
||||
nosuspend {
|
||||
writer.print(level_txt ++ prefix2 ++ format ++ "\n", args) catch return;
|
||||
writer.print(level_txt ++ prefix ++ format ++ "\n", args) catch return;
|
||||
bw.flush() catch return;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generic_format(object: anytype, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
|
||||
_ = fmt;
|
||||
_ = options;
|
||||
pub fn pretty_format(object: anytype, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
|
||||
try inner_format(object, fmt, options, writer, 0);
|
||||
}
|
||||
|
||||
fn inner_format(object: anytype, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype, comptime depth: u8) !void {
|
||||
const Object = @TypeOf(object);
|
||||
const object_info = @typeInfo(Object);
|
||||
switch (object_info) {
|
||||
.Struct => |s| {
|
||||
try writer.writeAll(@typeName(Object));
|
||||
try writer.writeAll(" = {\n");
|
||||
try writer.writeAll(" = struct {\n");
|
||||
inline for (s.fields) |field| {
|
||||
try writer.writeAll("\t .");
|
||||
try writer.writeAll("\t" ** (depth + 1));
|
||||
try writer.writeAll(".");
|
||||
try writer.writeAll(field.name);
|
||||
try writer.writeAll(" = ");
|
||||
// TODO check corresponding type and try to adapt fmt accordingly!
|
||||
try std.fmt.format(writer, "{any}", .{@field(object, field.name)});
|
||||
// TODO: pass along the already parsed formatting options too
|
||||
try inner_format(@field(object, field.name), fmt, options, writer, depth + 1);
|
||||
try writer.writeAll(",\n");
|
||||
}
|
||||
try writer.writeAll("\t" ** depth);
|
||||
try writer.writeAll("}");
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enhance_format(comptime object: type) type {
|
||||
// TODO: append a function to the type if it is a user defined type
|
||||
|
||||
// NOTE: this has the clear disadvantage that the type is not the same anymore! (but maybe this is still fine)
|
||||
const object_info = @typeInfo(object);
|
||||
switch (object_info) {
|
||||
.Struct => |s| {
|
||||
return @Type(.{
|
||||
.Struct = .{
|
||||
.layout = .auto,
|
||||
.fields = s.fields,
|
||||
.decls = s.decls,
|
||||
.is_tuple = false,
|
||||
},
|
||||
});
|
||||
.Enum => |e| {
|
||||
try writer.writeAll(@typeName(Object));
|
||||
try writer.writeAll(" = enum {\n");
|
||||
inline for (e.fields) |field| {
|
||||
try writer.writeAll("\t" ** (depth + 1));
|
||||
try writer.writeAll(field.name);
|
||||
try writer.writeAll(",\n");
|
||||
}
|
||||
try writer.writeAll("\t" ** depth);
|
||||
try writer.writeAll("} = ");
|
||||
try writer.writeAll(@tagName(object));
|
||||
},
|
||||
// TODO: implement prett_printing for other user defined types (`union` and `vector`)
|
||||
// TODO: recognize []const u8 types and print them as strings
|
||||
.Array => |a| {
|
||||
if (a.child == @TypeOf([:0]const u8)) {
|
||||
try std.fmt.format(writer, "\"{s}\"", .{object});
|
||||
} else {
|
||||
try std.fmt.format(writer, "[]{s}: {any}", .{ @typeName(a.child), object });
|
||||
}
|
||||
},
|
||||
.Vector => |v| {
|
||||
if (v.child == @TypeOf([:0]const u8)) {
|
||||
try std.fmt.format(writer, "\"{s}\"", .{object});
|
||||
} else {
|
||||
try std.fmt.format(writer, "[]{s}: {any}", .{ @typeName(v.child), object });
|
||||
}
|
||||
},
|
||||
else => {
|
||||
try std.fmt.format(writer, "{any}", .{object});
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user