97 lines
3.8 KiB
Zig
97 lines
3.8 KiB
Zig
const build_options = @import("build_options");
|
|
const c_time = if (build_options.timestamp) @cImport(@cInclude("time.h")) else null;
|
|
const std = @import("std");
|
|
|
|
pub const std_options: std.Options = .{
|
|
.logFn = logFn,
|
|
};
|
|
|
|
// zlog defaultLog function replacement, which adjusts the surrounding contents of every std.log message.
|
|
fn logFn(
|
|
comptime message_level: std.log.Level,
|
|
comptime scope: @Type(.EnumLiteral),
|
|
comptime format: []const u8,
|
|
args: anytype,
|
|
) void {
|
|
// TODO: provide build time configuration to allow tweaking corresponding output
|
|
// - change output file for writing messages to (default `stderr`)
|
|
const level_txt = comptime message_level.asText();
|
|
const prefix = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): ";
|
|
const stderr = std.io.getStdErr().writer();
|
|
var bw = std.io.bufferedWriter(stderr);
|
|
const writer = bw.writer();
|
|
|
|
std.debug.lockStdErr();
|
|
defer std.debug.unlockStdErr();
|
|
nosuspend {
|
|
if (build_options.timestamp) {
|
|
const curtime = c_time.time(null);
|
|
const tm = c_time.localtime(&curtime);
|
|
|
|
var buf: [32]u8 = undefined;
|
|
_ = c_time.strftime(@ptrCast(&buf), 32, "%F %R", tm);
|
|
writer.print("[{s}] ", .{buf}) catch return;
|
|
}
|
|
writer.print(level_txt ++ prefix ++ format ++ "\n", args) catch return;
|
|
bw.flush() catch return;
|
|
}
|
|
}
|
|
|
|
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(" = struct {\n");
|
|
inline for (s.fields) |field| {
|
|
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!
|
|
// 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("}");
|
|
},
|
|
.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});
|
|
},
|
|
}
|
|
}
|