A pretty printer for zig
zig

customizable color theme

altagos.dev 5c3efbdc 85e44017

verified
+80 -31
+4 -1
example/main.zig
··· 44 44 print("Boolean false - {f}\n", .{pretty(false)}); 45 45 print( 46 46 "Boolean true always with type name - {f}\n", 47 - .{Pretty(bool, .{ .always_show_type_names = true, .type_value_sep = ": " }).init(true)}, 47 + .{Pretty(bool, .{ 48 + .always_show_type_names = true, 49 + .theme = .{ .type_value_sep = ": " }, 50 + }).init(true)}, 48 51 ); 49 52 50 53 print("\nUnsigned Integers\n", .{});
+76 -30
pretty.zig
··· 11 11 show_type_names: bool = true, 12 12 always_show_type_names: bool = false, 13 13 14 + theme: Theme = .{}, 15 + }; 16 + 17 + pub const Theme = struct { 18 + pub const Colors = enum { 19 + dim, 20 + field, 21 + value, 22 + @"error", 23 + type, 24 + null, 25 + true, 26 + false, 27 + }; 28 + 14 29 field_name_type_sep: []const u8 = ": ", 15 30 type_value_sep: []const u8 = " = ", 31 + 32 + color_dim: Io.Terminal.Color = .dim, 33 + color_field: Io.Terminal.Color = .green, 34 + color_value: Io.Terminal.Color = .blue, 35 + color_error: Io.Terminal.Color = .red, 36 + color_type: Io.Terminal.Color = .bright_blue, 37 + color_null: Io.Terminal.Color = .cyan, 38 + color_true: Io.Terminal.Color = .bright_green, 39 + color_false: Io.Terminal.Color = .bright_red, 40 + 41 + pub fn getColor(this: Theme, option: Colors) Io.Terminal.Color { 42 + return switch (option) { 43 + // .dim => this.color_dim, 44 + // .field => this.color_field, 45 + // .value => this.color_value, 46 + // .@"error" => this.color_error, 47 + // .type => this.color_type, 48 + // .null => this.color_null, 49 + // .true => this.color_true, 50 + // .false => this.color_false, 51 + inline else => |opt| @field(this, "color_" ++ @tagName(opt)), 52 + }; 53 + } 16 54 }; 17 55 18 56 const default_options: Options = if (@hasDecl(root, "pretty_options")) root.pretty_options else .{}; ··· 74 112 return this.out.writeAll(text); 75 113 } 76 114 77 - pub inline fn setColor(this: RuntimeContext, color: Io.Terminal.Color) void { 115 + pub inline fn setColor( 116 + this: RuntimeContext, 117 + comptime ctx: ComptimeContext, 118 + color: Theme.Colors, 119 + ) void { 120 + this.tty.setColor(ctx.options.theme.getColor(color)) catch {}; 121 + } 122 + 123 + pub inline fn setColorRaw(this: RuntimeContext, color: Io.Terminal.Color) void { 78 124 this.tty.setColor(color) catch {}; 79 125 } 80 126 ··· 113 159 if (opts.dont_skip_type_name) try printType(T, cctx, rctx); 114 160 115 161 return switch (info) { 116 - .bool => formatBool(rctx, value), 117 - .null => formatNull(rctx), 118 - .type => formatType(rctx, value), 162 + .bool => formatBool(cctx, rctx, value), 163 + .null => formatNull(cctx, rctx), 164 + .type => formatType(cctx, rctx, value), 119 165 120 166 // comptime types 121 167 .comptime_int, ··· 126 172 // enum types 127 173 .@"enum", 128 174 .enum_literal, 129 - => formatValue(rctx, value), 175 + => formatValue(cctx, rctx, value), 130 176 131 177 .optional => |opt| formatOptional(opt.child, cctx, rctx, value), 132 178 .@"struct" => |st| formatStruct(T, st, cctx, rctx, value), 133 179 134 180 else => { 135 - rctx.setColor(.red); 181 + rctx.setColor(cctx, .@"error"); 136 182 try rctx.print("Unimplemented! ({} = {any})", .{ info, value }); 137 183 rctx.resetColor(); 138 184 }, ··· 151 197 }; 152 198 153 199 if ((cctx.depth != 0 or cctx.options.always_show_type_names) and !excluded) { 154 - rctx.setColor(.dim); 200 + rctx.setColor(cctx, .dim); 155 201 156 202 if (cctx.options.show_type_names) { 157 203 try rctx.write(@typeName(T)); 158 204 } 159 - try rctx.write(cctx.options.type_value_sep); 205 + try rctx.write(cctx.options.theme.type_value_sep); 160 206 161 207 rctx.resetColor(); 162 208 } 163 209 } 164 210 165 - inline fn formatBool(ctx: RuntimeContext, value: bool) !void { 166 - ctx.setColor(if (value) .bright_green else .bright_red); 167 - try ctx.print("{}", .{value}); 168 - ctx.resetColor(); 211 + inline fn formatBool(comptime cctx: ComptimeContext, rctx: RuntimeContext, value: bool) !void { 212 + rctx.setColor(cctx, if (value) .true else .false); 213 + try rctx.print("{}", .{value}); 214 + rctx.resetColor(); 169 215 } 170 216 171 - inline fn formatNull(ctx: RuntimeContext) !void { 172 - ctx.setColor(.cyan); 173 - try ctx.write("null"); 174 - ctx.resetColor(); 217 + inline fn formatNull(comptime cctx: ComptimeContext, rctx: RuntimeContext) !void { 218 + rctx.setColor(cctx, .null); 219 + try rctx.write("null"); 220 + rctx.resetColor(); 175 221 } 176 222 177 223 inline fn formatOptional( ··· 183 229 return if (value) |val| 184 230 innerFmt(T, cctx, rctx, val, .{ .dont_skip_type_name = false }) 185 231 else 186 - formatNull(rctx); 232 + formatNull(cctx, rctx); 187 233 } 188 234 189 235 inline fn formatStruct( ··· 201 247 }; 202 248 203 249 if (cctx.options.inline_structs) { 204 - rctx.setColor(.dim); 250 + rctx.setColor(cctx, .dim); 205 251 try rctx.write(".{ "); 206 252 rctx.resetColor(); 207 253 } ··· 211 257 indent(next_cctx, rctx); 212 258 if (index != 0 and cctx.options.inline_structs) try rctx.write(", "); 213 259 214 - rctx.setColor(.green); 215 - try rctx.write("." ++ field.name ++ cctx.options.field_name_type_sep); 260 + rctx.setColor(cctx, .field); 261 + try rctx.write("." ++ field.name ++ cctx.options.theme.field_name_type_sep); 216 262 rctx.resetColor(); 217 263 218 264 try innerFmt(field.type, next_cctx, rctx, @field(value, field.name), .{}); ··· 221 267 } 222 268 223 269 if (cctx.options.inline_structs) { 224 - rctx.setColor(.dim); 270 + rctx.setColor(cctx, .dim); 225 271 try rctx.write(" }"); 226 272 rctx.resetColor(); 227 273 } 228 274 } 229 275 230 - inline fn formatType(ctx: RuntimeContext, value: type) !void { 231 - ctx.setColor(.bright_blue); 232 - ctx.setColor(.bold); 233 - try ctx.write(@typeName(value)); 234 - ctx.resetColor(); 276 + inline fn formatType(comptime cctx: ComptimeContext, rctx: RuntimeContext, value: type) !void { 277 + rctx.setColor(cctx, .type); 278 + rctx.setColorRaw(.bold); 279 + try rctx.write(@typeName(value)); 280 + rctx.resetColor(); 235 281 } 236 282 237 - inline fn formatValue(ctx: RuntimeContext, value: anytype) !void { 238 - ctx.setColor(.blue); 239 - try ctx.print("{}", .{value}); 240 - ctx.resetColor(); 283 + inline fn formatValue(comptime cctx: ComptimeContext, rctx: RuntimeContext, value: anytype) !void { 284 + rctx.setColor(cctx, .value); 285 + try rctx.print("{}", .{value}); 286 + rctx.resetColor(); 241 287 } 242 288 243 289 inline fn indent(comptime cctx: ComptimeContext, rctx: RuntimeContext) void {