diff --git a/build.zig b/build.zig index 09ebd1f..c9066fe 100644 --- a/build.zig +++ b/build.zig @@ -8,6 +8,7 @@ pub fn build(b: *Build) void { const options = b.addOptions(); const known_folders = b.dependency("known_folders", .{}).module("known-folders"); + const pretty = b.dependency("pretty", .{}).module("pretty"); const meta = b.createModule(.{ .root_source_file = b.path("src/meta/root.zig"), @@ -46,6 +47,7 @@ pub fn build(b: *Build) void { .{ .name = "st", .module = st }, .{ .name = "agent", .module = agent }, .{ .name = "meta", .module = meta }, + .{ .name = "pretty", .module = pretty }, }, }); diff --git a/build.zig.zon b/build.zig.zon index a88d761..8b3de74 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -6,6 +6,10 @@ .url = "git+https://github.com/ziglibs/known-folders.git?ref=master#82027007c0eb199a3242c167a5cffd83b6ee571b", .hash = "known_folders-0.0.0-Fy-PJqHJAAB43zDJmOdlr3nViu69IFI9pNFt7hkHjKk4", }, + .pretty = .{ + .url = "git+https://git.sr.ht/~altagos/pretty?ref=main#a025f81f4b9a1a6be483a4c33fafc6e0ef5cae6f", + .hash = "pretty-0.1.0--Y3D26JKAAABPfRqFy6oUakwiYAawqqbU6xF0_5ziP-l", + }, }, .minimum_zig_version = "0.16.0-dev.1246+4b593a6c2", .paths = .{ diff --git a/src/main.zig b/src/main.zig index d83b7ee..5522045 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,6 +1,6 @@ const std = @import("std"); -const pretty = @import("meta").pretty; +const pretty = @import("pretty").pretty; const meta = @import("meta"); diff --git a/src/meta/fmt.zig b/src/meta/fmt.zig deleted file mode 100644 index 097e4a0..0000000 --- a/src/meta/fmt.zig +++ /dev/null @@ -1,457 +0,0 @@ -const std = @import("std"); -const Io = std.Io; -const Type = std.builtin.Type; - -pub fn pretty(value: anytype) Pretty(@TypeOf(value)) { - return Pretty(@TypeOf(value)).init(value); -} - -fn Context(comptime runtime: bool) type { - if (runtime) { - return struct { - indent_width: u8 = 2, - indent_level: usize = 0, - }; - } else { - return struct { - indent_width: comptime_int = 2, - indent_level: comptime_int = 0, - }; - } -} - -const Options = struct { - type_name: bool = true, - last_layer_type_name: bool = true, - - follow_pointers: bool = true, -}; - -pub fn Pretty(comptime T: type) type { - const global = struct { - var conf: ?std.Io.Terminal = null; - }; - return struct { - value: T, - pub fn init(val: T) @This() { - return .{ .value = val }; - } - pub fn format(this: *const @This(), w: *std.Io.Writer) error{WriteFailed}!void { - if (global.conf == null) { - var buffer: [64]u8 = undefined; - const stderr = std.debug.lockStderr(&buffer).terminal(); - global.conf = stderr; - global.conf.?.writer = w; - std.debug.unlockStderr(); - } - std.log.debug("", .{}); - return innerFmt(w, global.conf.?, T, this.value, !@inComptime(), .{}, .{}); - } - }; -} - -const Color = enum { - dim, - reset, - text, - field, - value, -}; - -fn setColor( - tty: Io.Terminal, - color: Color, -) void { - switch (color) { - .dim => { - tty.setColor(.dim) catch {}; - }, - .reset => { - tty.setColor(.reset) catch {}; - }, - .text => { - // tty.setColor(.italic) catch {}; - tty.setColor(.dim) catch {}; - tty.setColor(.blue) catch {}; - }, - .field => { - tty.setColor(.green) catch {}; - }, - .value => { - // tty.setColor(.italic) catch {}; - tty.setColor(.blue) catch {}; - }, - } -} - -fn innerFmt( - w: *std.Io.Writer, - tty: std.Io.Terminal, - comptime T: type, - value: T, - comptime runtime: bool, - ctx: Context(runtime), - opts: Options, -) error{WriteFailed}!void { - const info = @typeInfo(T); - - switch (info) { - .bool => try printBool(w, tty, value, opts), - .int => |int| try printInt(w, tty, int, value, opts), - .float => |float| try printFloat(w, tty, float, value, opts), - .@"enum", .enum_literal => try printEnum(w, tty, value, opts), - .optional => |optional| try printOptional(w, tty, optional, value, runtime, ctx, opts), - .pointer => |ptr| { - if (opts.follow_pointers) { - try printPointer(w, tty, ptr, value, runtime, ctx, opts); - } else {} - }, - .array => |array| try printArray(w, tty, array, value, runtime, ctx, opts), - .@"struct" => |str| try printStruct(T, w, tty, str, value, runtime, ctx, opts), - else => { - tty.setColor(.red) catch {}; - try w.print("Unimplemented! ({})", .{info}); - setColor(tty, .reset); - }, - } -} - -fn printBool( - w: *Io.Writer, - tty: Io.Terminal, - value: bool, - opts: Options, -) !void { - if (opts.type_name) { - setColor(tty, .dim); - try w.print("bool => ", .{}); - setColor(tty, .reset); - } else { - tty.setColor(.dim) catch {}; - try w.print("=> ", .{}); - setColor(tty, .reset); - } - setColor(tty, .value); - if (value) { - tty.setColor(.bright_green) catch {}; - } else { - tty.setColor(.bright_red) catch {}; - } - try w.print("{}", .{value}); - setColor(tty, .reset); -} - -fn printInt( - w: *Io.Writer, - tty: Io.Terminal, - int: Type.Int, - value: anytype, - opts: Options, -) !void { - if (opts.type_name) { - tty.setColor(.dim) catch {}; - try w.print("{s}{} => ", .{ if (int.signedness == .signed) "i" else "u", int.bits }); - setColor(tty, .reset); - } else { - tty.setColor(.dim) catch {}; - try w.print("=> ", .{}); - setColor(tty, .reset); - } - setColor(tty, .value); - try w.print("{}", .{value}); - setColor(tty, .reset); -} - -fn printFloat( - w: *Io.Writer, - tty: Io.Terminal, - float: Type.Float, - value: anytype, - opts: Options, -) !void { - if (opts.type_name) { - tty.setColor(.dim) catch {}; - try w.print("f{} => ", .{float.bits}); - setColor(tty, .reset); - } else { - tty.setColor(.dim) catch {}; - try w.print("=> ", .{}); - setColor(tty, .reset); - } - setColor(tty, .value); - try w.print("{}", .{value}); - setColor(tty, .reset); -} - -fn printEnum( - w: *Io.Writer, - tty: Io.Terminal, - value: anytype, - opts: Options, -) !void { - if (opts.type_name) { - tty.setColor(.dim) catch {}; - try w.print("{s} => ", .{@typeName(@TypeOf(value))}); - setColor(tty, .reset); - } else { - tty.setColor(.dim) catch {}; - try w.print("=> ", .{}); - setColor(tty, .reset); - } - setColor(tty, .value); - try w.print("{}", .{value}); - setColor(tty, .reset); -} - -fn printOptional( - w: *Io.Writer, - tty: Io.Terminal, - optional: Type.Optional, - value: anytype, - comptime runtime: bool, - ctx: Context(runtime), - opts: Options, -) !void { - var next_opts = opts; - next_opts.type_name = if (!opts.type_name and !opts.last_layer_type_name) false else true; - next_opts.last_layer_type_name = opts.type_name; - - if (opts.type_name) { - tty.setColor(.dim) catch {}; - try w.print("?", .{}); - setColor(tty, .reset); - } - - if (value) |val| { - try innerFmt(w, tty, optional.child, val, runtime, ctx, next_opts); - } else { - if (opts.type_name) { - tty.setColor(.dim) catch {}; - try w.print("{s} => ", .{@typeName(optional.child)}); - setColor(tty, .reset); - } else { - tty.setColor(.dim) catch {}; - try w.print("=> ", .{}); - setColor(tty, .reset); - } - - tty.setColor(.blue) catch {}; - try w.writeAll("null"); - setColor(tty, .reset); - } -} - -fn printArray( - w: *Io.Writer, - tty: Io.Terminal, - array: Type.Array, - value: anytype, - comptime runtime: bool, - ctx: Context(runtime), - opts: Options, -) !void { - comptime var next_ctx = ctx; - - var next_opts = opts; - next_opts.type_name = if (!opts.type_name and !opts.last_layer_type_name) false else true; - next_opts.last_layer_type_name = opts.type_name; - - if (opts.type_name) { - tty.setColor(.dim) catch {}; - try w.print("[{}]{s} =>", .{ array.len, @typeName(array.child) }); - setColor(tty, .reset); - } else { - tty.setColor(.dim) catch {}; - try w.print("=> ", .{}); - setColor(tty, .reset); - } - - inline for (value, 0..) |item, idx| { - try indent(w, runtime, ctx); - - setColor(tty, .field); - try w.print("[{}] ", .{idx}); - setColor(tty, .reset); - - next_ctx.indent_level = ctx.indent_level + 1; - next_opts.type_name = false; - - try innerFmt(w, tty, @TypeOf(item), item, runtime, next_ctx, next_opts); - } -} - -fn printPointer( - w: *Io.Writer, - tty: Io.Terminal, - ptr: Type.Pointer, - value: anytype, - comptime runtime: bool, - ctx: Context(runtime), - opts: Options, -) !void { - var next_opts = opts; - next_opts.type_name = if (!opts.type_name and !opts.last_layer_type_name) false else true; - next_opts.last_layer_type_name = opts.type_name; - - switch (ptr.size) { - .one => { - if (opts.type_name) { - tty.setColor(.dim) catch {}; - try w.print("*{s}", .{if (ptr.is_const) "const " else ""}); - setColor(tty, .reset); - } - - if (ptr.child == anyopaque or @typeInfo(ptr.child) == .@"fn") - return; - - try innerFmt(w, tty, ptr.child, value, runtime, ctx, next_opts); - }, - .slice => { - if (opts.type_name) { - setColor(tty, .dim); - try w.print("[]{s}", .{if (ptr.is_const) "const " else ""}); - setColor(tty, .reset); - } - - if (ptr.child == u8) { - tty.setColor(.dim) catch {}; - try w.print("{s}=>", .{if (opts.type_name) "u8 " else ""}); - setColor(tty, .reset); - - try indent(w, runtime, ctx); - - setColor(tty, .text); - try w.print("\"{s}\"", .{value}); - setColor(tty, .reset); - return; - } - - setColor(tty, .dim); - try w.print("{s}{s}", .{ - if (opts.type_name) @typeName(ptr.child) else "", - if (opts.type_name) " =>" else "=>", - }); - setColor(tty, .reset); - - const run_ctx: Context(true) = .{ .indent_width = ctx.indent_width, .indent_level = ctx.indent_level }; - var next_ctx: Context(true) = .{ .indent_width = ctx.indent_width, .indent_level = ctx.indent_level }; - - var count: usize = 0; - for (value, 0..) |item, idx| { - try indent(w, true, run_ctx); - - setColor(tty, .field); - try w.print("[{}] ", .{idx}); - setColor(tty, .reset); - - next_ctx.indent_level = ctx.indent_level + 1; - next_opts.type_name = false; - - try innerFmt(w, tty, @TypeOf(item), item, true, next_ctx, next_opts); - count += 1; - } - - if (count == 0) { - setColor(tty, .dim); - try w.writeAll(" empty"); - setColor(tty, .reset); - } - }, - else => { - try w.print("unimplemented {}", .{ptr}); - }, - } -} - -fn printStruct( - comptime T: type, - w: *Io.Writer, - tty: Io.Terminal, - str: Type.Struct, - value: anytype, - comptime runtime: bool, - ctx: Context(runtime), - opts: Options, -) !void { - var next_opts = opts; - next_opts.type_name = if (!opts.type_name and !opts.last_layer_type_name) false else true; - next_opts.last_layer_type_name = opts.type_name; - - setColor(tty, .dim); - if (opts.type_name) { - try w.print("{s} =>", .{@typeName(T)}); - } else { - try w.print("=>", .{}); - } - setColor(tty, .reset); - - if (runtime) { - var next_ctx: Context(true) = ctx; - - inline for (str.fields) |field| { - try indent(w, runtime, ctx); - - setColor(tty, .field); - try w.print(".{s}", .{field.name}); - setColor(tty, .reset); - - setColor(tty, .dim); - if (opts.type_name) { - try w.writeAll(": "); - } else try w.writeByte(' '); - setColor(tty, .reset); - - next_ctx.indent_level = ctx.indent_level + 1; - - try innerFmt( - w, - tty, - field.type, - @field(value, field.name), - runtime, - next_ctx, - next_opts, - ); - } - } else { - comptime var next_ctx: Context(false) = ctx; - - inline for (str.fields) |field| { - try indent(w, runtime, ctx); - - setColor(tty, .field); - try w.print(".{s}", .{field.name}); - setColor(tty, .reset); - - setColor(tty, .dim); - if (opts.type_name) { - try w.writeAll(": "); - } else try w.writeByte(' '); - setColor(tty, .reset); - - next_ctx.indent_level = ctx.indent_level + 1; - - try innerFmt( - w, - tty, - field.type, - @field(value, field.name), - runtime, - next_ctx, - next_opts, - ); - } - } -} - -fn indent(w: *Io.Writer, comptime runtime: bool, ctx: Context(runtime)) !void { - try w.writeByte('\n'); - if (runtime) { - for (0..((ctx.indent_level + 1) * ctx.indent_width)) |_| { - try w.writeByte(' '); - } - } else { - const text: [(ctx.indent_level + 1) * ctx.indent_width]u8 = @splat(' '); - try w.writeAll(&text); - } -} diff --git a/src/meta/root.zig b/src/meta/root.zig index 80564c3..03ce559 100644 --- a/src/meta/root.zig +++ b/src/meta/root.zig @@ -1,7 +1,3 @@ -pub const fmt = @import("fmt.zig"); - -pub const pretty = fmt.pretty; - pub fn CombinedEnum(comptime parent: type) type { const parent_info = @typeInfo(parent).@"struct";