mod: rename file to be more agnostic to zig language styling
This commit is contained in:
201
src/root.zig
Normal file
201
src/root.zig
Normal file
@@ -0,0 +1,201 @@
|
||||
/// *zlog* defaultLog function replacement, which adjusts the surrounding contents of every `std.log` message.
|
||||
fn logFn(
|
||||
comptime message_level: log.Level,
|
||||
comptime scope: @Type(.enum_literal),
|
||||
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`)
|
||||
// - write into own file for each level?
|
||||
|
||||
const prefix = if (scope == .default) ": " else "(\x1b[2m" ++ @tagName(scope) ++ "\x1b[0m): ";
|
||||
const level_txt = switch (comptime message_level) {
|
||||
.err => "[\x1b[38;5;9merror\x1b[0m]",
|
||||
.warn => "[\x1b[38;5;11mwarning\x1b[0m]",
|
||||
.info => "[\x1b[38;5;10minfo\x1b[0m]",
|
||||
.debug => "[\x1b[38;5;12mdebug\x1b[0m]",
|
||||
};
|
||||
const complete_format = level_txt ++ prefix ++ format ++ "\n";
|
||||
if (comptime build_options.file.len != 0) {
|
||||
// TODO handle errors accordingly (i.e. panic?)
|
||||
// NOTE with zig 0.13.0 there is currently no way to open files to append (except to use libc or talk directly to posix, which this lib should not have to do)
|
||||
const file = std.fs.openFileAbsolute(build_options.file, .{
|
||||
.mode = .read_write,
|
||||
}) catch std.fs.createFileAbsolute(build_options.file, .{
|
||||
.truncate = false,
|
||||
}) catch @panic("Failed to open and/or create configured log file");
|
||||
defer file.close();
|
||||
|
||||
var buffer = io.bufferedWriter(file.writer());
|
||||
defer buffer.flush() catch {};
|
||||
|
||||
const writer = buffer.writer();
|
||||
log_writing(writer, fmt, args);
|
||||
}
|
||||
|
||||
if (comptime build_options.stderr) {
|
||||
var buffer = io.bufferedWriter(stderr().deprecatedWriter());
|
||||
defer buffer.flush() catch {};
|
||||
|
||||
std.debug.lockStdErr();
|
||||
defer std.debug.unlockStdErr();
|
||||
|
||||
const writer = buffer.writer();
|
||||
log_writing(writer, complete_format, args);
|
||||
}
|
||||
}
|
||||
|
||||
inline fn log_writing(writer: anytype, comptime format: []const u8, args: anytype) void {
|
||||
nosuspend {
|
||||
if (build_options.timestamp) log_timestamp(writer);
|
||||
writer.print(format, args) catch return;
|
||||
}
|
||||
}
|
||||
|
||||
inline fn log_timestamp(writer: anytype) void {
|
||||
writer.print("[\x1b[1m{any}\x1b[0m] ", .{ztime.DateTime.now()}) catch return;
|
||||
}
|
||||
|
||||
pub fn pretty_format(object: anytype, comptime format: []const u8, options: fmt.FormatOptions, writer: anytype) !void {
|
||||
try inner_format(object, format, options, writer, 0);
|
||||
}
|
||||
|
||||
fn inner_format(object: anytype, comptime format: []const u8, options: 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), format, 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));
|
||||
},
|
||||
.@"union" => |u| {
|
||||
try writer.writeAll(@typeName(Object));
|
||||
try writer.writeAll(" = union");
|
||||
if (u.tag_type) |Tag| {
|
||||
_ = Tag;
|
||||
try writer.writeAll("(enum)");
|
||||
}
|
||||
try writer.writeAll(" {\n");
|
||||
inline for (u.fields) |field| {
|
||||
try writer.writeAll("\t" ** (depth + 1));
|
||||
try writer.writeAll(field.name);
|
||||
if (@typeInfo(field.type) != .void) {
|
||||
try writer.writeAll(": ");
|
||||
try writer.writeAll(@typeName(field.type));
|
||||
}
|
||||
try writer.writeAll(",\n");
|
||||
}
|
||||
try writer.writeAll("\t" ** depth);
|
||||
try writer.writeAll("} = ");
|
||||
if (u.tag_type) |Tag| {
|
||||
try writer.writeAll(".{ .");
|
||||
try writer.writeAll(@tagName(object));
|
||||
try writer.writeAll(" = ");
|
||||
inline for (u.fields) |u_field| if (object == @field(Tag, u_field.name)) {
|
||||
try inner_format(@field(object, u_field.name), format, options, writer, depth + 1);
|
||||
};
|
||||
try writer.writeAll(" }");
|
||||
} else {
|
||||
// NOTE the value of a union (untagged) is displayed like this also in the standard library,
|
||||
// not sure if you can reflect the used variant (and its value)
|
||||
try fmt.format(writer, "@{x}", .{@intFromPtr(&object)});
|
||||
}
|
||||
},
|
||||
.pointer => |p| switch (p.size) {
|
||||
.slice => switch (@typeInfo(p.child)) {
|
||||
.int => |num| {
|
||||
if (num.signedness != .unsigned) {
|
||||
try fmt.format(writer, "[]{s}: {any}", .{ @typeName(p.child), object });
|
||||
} else {
|
||||
switch (num.bits) {
|
||||
8 => try fmt.format(writer, "\"{s}\"", .{object}),
|
||||
else => try fmt.format(writer, "[]{s}: {any}", .{ @typeName(p.child), object }),
|
||||
}
|
||||
}
|
||||
},
|
||||
else => try fmt.format(writer, "[]{s}: {any}", .{ @typeName(p.child), object }),
|
||||
},
|
||||
.c => switch (@typeInfo(p.child)) {
|
||||
.int => |num| {
|
||||
if (num.signedness != .unsigned) {
|
||||
try fmt.format(writer, "[*c]{s}: {any}", .{ @typeName(p.child), object });
|
||||
} else {
|
||||
switch (num.bits) {
|
||||
8 => try fmt.format(writer, "\"{s}\"", .{object}),
|
||||
else => try fmt.format(writer, "[*c]{s}: {any}", .{ @typeName(p.child), object }),
|
||||
}
|
||||
}
|
||||
},
|
||||
else => try fmt.format(writer, "[]{s}: {any}", .{ @typeName(p.child), object }),
|
||||
},
|
||||
.many => try fmt.format(writer, "[*]{s}: {any}", .{ @typeName(p.child), object }),
|
||||
.one => try fmt.format(writer, "[1]{s}: {any}", .{ @typeName(p.child), object }),
|
||||
},
|
||||
.array => |a| switch (@typeInfo(a.child)) {
|
||||
.int => |num| {
|
||||
if (num.signedness != .unsigned) {
|
||||
try fmt.format(writer, "[]{s}: {any}", .{ @typeName(a.child), object });
|
||||
} else {
|
||||
switch (num.bits) {
|
||||
8 => try fmt.format(writer, "\"{s}\"", .{object}),
|
||||
else => try fmt.format(writer, "[]{s}: {any}", .{ @typeName(a.child), object }),
|
||||
}
|
||||
}
|
||||
},
|
||||
else => try fmt.format(writer, "[]{s}: {any}", .{ @typeName(a.child), object }),
|
||||
},
|
||||
.vector => |v| switch (@typeInfo(v.child)) {
|
||||
.int => |num| {
|
||||
if (num.signedness != .unsigned) {
|
||||
try fmt.format(writer, "[]{s}: {any}", .{ @typeName(v.child), object });
|
||||
} else {
|
||||
switch (num.bits) {
|
||||
8 => try fmt.format(writer, "\"{s}\"", .{object}),
|
||||
else => try fmt.format(writer, "[]{s}: {any}", .{ @typeName(v.child), object }),
|
||||
}
|
||||
}
|
||||
},
|
||||
else => try fmt.format(writer, "[]{s}: {any}", .{ @typeName(v.child), object }),
|
||||
},
|
||||
else => try fmt.format(writer, "{any}", .{object}),
|
||||
}
|
||||
}
|
||||
|
||||
pub const std_options: std.Options = .{
|
||||
.logFn = logFn,
|
||||
};
|
||||
|
||||
const std = @import("std");
|
||||
const io = std.io;
|
||||
const fs = std.fs;
|
||||
const stderr = fs.File.stderr;
|
||||
const log = std.log;
|
||||
const fmt = std.fmt;
|
||||
const build_options = @import("build_options");
|
||||
const ztime = if (build_options.timestamp) @import("ztime") else null;
|
||||
Reference in New Issue
Block a user