A pretty printer for zig
zig

pretty pointers

altagos.dev 2aff8792 9d24ba6c

verified
+241 -4
+56
example/employees.json
··· 1 + { 2 + "employee": { 3 + "id": "E00001", 4 + "name": "Bryan Smith", 5 + "position": "Chemical engineer", 6 + "department": { 7 + "id": "D080", 8 + "name": "Incentivize", 9 + "manager": { 10 + "id": "M2858", 11 + "name": "Rebecca Andrews", 12 + "contact": { 13 + "email": "amanda52@example.net", 14 + "phone": "815-823-1247x52270" 15 + } 16 + } 17 + }, 18 + "projects": [ 19 + { 20 + "projectId": "P5216", 21 + "projectName": "Multi-tiered discrete Internet solution", 22 + "startDate": "2025-05-25", 23 + "tasks": [ 24 + { 25 + "taskId": "T522", 26 + "title": "Evolve Best-Of-Breed E-Tailers", 27 + "status": "In Progress", 28 + "details": { 29 + "hoursSpent": 41, 30 + "technologiesUsed": [ 31 + "Python", 32 + "SQL" 33 + ], 34 + "expectedCompletion": "2025-09-11" 35 + } 36 + }, 37 + { 38 + "taskId": "T405", 39 + "title": "Empower Cross-Media Users", 40 + "status": "In Progress", 41 + "details": { 42 + "hoursSpent": 41, 43 + "technologiesUsed": [ 44 + "PyTorch", 45 + "JavaScript", 46 + "Python", 47 + "Scikit-learn" 48 + ], 49 + "expectedCompletion": "2025-08-17" 50 + } 51 + } 52 + ] 53 + } 54 + ] 55 + } 56 + }
+81 -2
example/main.zig
··· 9 9 .always_show_type_names = true, 10 10 }; 11 11 12 + const employees = @embedFile("employees.json"); 13 + 12 14 const Hello = enum { world, developer }; 13 15 14 16 const Gender = enum(u8) { male, female, nonbinary, other, _ }; ··· 35 37 person: [2]Person, 36 38 }; 37 39 40 + const Employee = struct { 41 + id: []const u8, 42 + name: []const u8, 43 + position: []const u8, 44 + department: Department, 45 + projects: []Project, 46 + }; 47 + 48 + const Department = struct { 49 + id: []const u8, 50 + name: []const u8, 51 + manager: Manager, 52 + 53 + const Manager = struct { 54 + id: []const u8, 55 + name: []const u8, 56 + contact: Contact, 57 + 58 + const Contact = struct { 59 + email: []const u8, 60 + phone: []const u8, 61 + }; 62 + }; 63 + }; 64 + 65 + const Project = struct { 66 + projectId: []const u8, 67 + projectName: []const u8, 68 + startDate: []const u8, 69 + tasks: []Task, 70 + 71 + const Task = struct { 72 + taskId: []const u8, 73 + title: []const u8, 74 + status: []const u8, 75 + details: Details, 76 + 77 + const Details = struct { 78 + hoursSpent: u32, 79 + technologiesUsed: [][]const u8, 80 + expectedCompletion: []const u8, 81 + }; 82 + }; 83 + }; 84 + 85 + const JsonData = union(enum) { 86 + employee: Employee, 87 + }; 88 + 38 89 const ErrorSet = error{ OutOfMemory, WriteFailed }; 39 90 const Result = ErrorSet!Hello; 40 91 41 92 pub fn main(init: std.process.Init) !void { 42 - _ = init; 43 - 44 93 print("Pretty type - {f}\n", .{pretty(Hello)}); 45 94 print("Pretty null - {f}\n", .{pretty(null)}); 46 95 ··· 124 173 print("\nVectors\n", .{}); 125 174 print("Pretty vector of u8s - {f}\n", .{pretty(zig_logo_color)}); 126 175 176 + const ptr_array = [_]f32{ 0.1, 0.3, 0.9 }; 177 + const persons_allocated = try init.gpa.alloc(Person, 10); 178 + defer init.gpa.free(persons_allocated); 179 + 180 + var str_allocated = try init.gpa.alloc(u8, 5); 181 + defer init.gpa.free(str_allocated); 182 + str_allocated[0] = 'H'; 183 + str_allocated[1] = 'e'; 184 + str_allocated[2] = 'l'; 185 + str_allocated[3] = 'l'; 186 + str_allocated[4] = 'o'; 187 + 188 + var buffer: [100]u8 = [_]u8{1} ** 100; 189 + const buffer_ptr: *[100]u8 = &buffer; 190 + const buffer_many_ptr: [*]u8 = buffer_ptr; 191 + 192 + print("\nPointers\n", .{}); 193 + print("Pretty string - {f}\n", .{pretty("Hello World!")}); 194 + print("Pretty ptr to an array - {f}\n", .{pretty(&ptr_array)}); 195 + print("Pretty ptr to nested struct - {f}\n", .{pretty(&nested)}); 196 + print("Pretty ptr to slice of structs - {f}\n", .{pretty(persons_allocated)}); 197 + print("Pretty ptr to slice of u8 - {f}\n", .{pretty(str_allocated)}); 198 + print("Pretty ptr to buffer many ptr - {f}\n", .{pretty(buffer_many_ptr)}); 199 + 127 200 const eu_error: Result = error.OutOfMemory; 128 201 const eu_ok: Result = .world; 129 202 ··· 135 208 print("\nFunctions\n", .{}); 136 209 print("Pretty function pretty - {f}\n", .{pretty(pretty)}); 137 210 print("Pretty function main - {f}\n", .{pretty(main)}); 211 + 212 + const parsed: std.json.Parsed(JsonData) = try std.json.parseFromSlice(JsonData, init.gpa, employees, .{}); 213 + defer parsed.deinit(); 214 + 215 + print("\nJson\n", .{}); 216 + print("{}", .{parsed.value}); 138 217 }
+104 -2
pretty.zig
··· 24 24 25 25 inline_arrays: bool = false, 26 26 always_show_index: bool = false, 27 - treat_u8_arrays_as_strings: bool = true, 27 + 28 + treat_u8_ptr_as_string: bool = true, 29 + treat_u8_ptr_slice_as_string: bool = true, 30 + inline_slice: bool = false, 28 31 29 32 inline_structs: bool = false, 30 33 ··· 41 44 value, 42 45 @"error", 43 46 type, 47 + string, 48 + many_ptr, 44 49 null, 45 50 true, 46 51 false, ··· 58 63 color_value: Io.Terminal.Color = .blue, 59 64 color_error: Io.Terminal.Color = .red, 60 65 color_type: Io.Terminal.Color = .bright_blue, 66 + color_string: Io.Terminal.Color = .magenta, 67 + color_many_ptr: Io.Terminal.Color = .magenta, 61 68 color_null: Io.Terminal.Color = .cyan, 62 69 color_true: Io.Terminal.Color = .bright_green, 63 70 color_false: Io.Terminal.Color = .bright_red, ··· 206 213 .error_union => formatErrorUnion(ctx, run, value), 207 214 208 215 .array => |arr| formatArray(ctx, arr, run, value), 209 - // TODO: .pointer => |ptr| {}, 210 216 .vector => |vec| formatVector(ctx, vec, run, value), 211 217 212 218 .@"fn" => formatFn(T, ctx, run), 213 219 220 + .pointer => |ptr| switch (ptr.size) { 221 + .one => formatPtrOne(ctx, ptr, run, value), 222 + .slice => formatPtrSlice(ctx, ptr, run, value), 223 + .many => formatPtrMany(ctx, ptr, run, value), 224 + else => { 225 + run.setColor(ctx, .@"error"); 226 + try run.print("Unimplemented! ({} = {any})", .{ info, value }); 227 + run.resetColor(); 228 + }, 229 + }, 230 + 214 231 else => { 215 232 run.setColor(ctx, .@"error"); 216 233 try run.print("Unimplemented! ({} = {any})", .{ info, value }); ··· 413 430 414 431 run.setColor(ctx, .dim); 415 432 try run.write(" )"); 433 + run.resetColor(); 434 + } 435 + 436 + inline fn formatPtrOne( 437 + comptime ctx: Context, 438 + comptime ptr: Type.Pointer, 439 + run: *Runtime, 440 + value: anytype, 441 + ) !void { 442 + const is_string = switch (@typeInfo(ptr.child)) { 443 + .array => |arr| arr.child == u8 and ctx.options.treat_u8_ptr_as_string, 444 + else => false, 445 + }; 446 + if (is_string) return formatString(ctx, run, value); 447 + 448 + try innerFmt(ptr.child, ctx, run, value.*, .{ .skip_type_name = true }); 449 + } 450 + 451 + inline fn formatPtrSlice( 452 + comptime ctx: Context, 453 + comptime ptr: Type.Pointer, 454 + run: *Runtime, 455 + value: anytype, 456 + ) !void { 457 + if (ptr.child == u8 and ctx.options.treat_u8_ptr_slice_as_string) 458 + return formatString(ctx, run, value); 459 + 460 + const next_ctx = Context{ 461 + .depth = ctx.depth + 1, 462 + .exited_comptime = ctx.exited_comptime, 463 + .options = ctx.options, 464 + }; 465 + 466 + if (ctx.options.inline_slice) { 467 + run.setColor(ctx, .dim); 468 + try run.write("{ "); 469 + run.resetColor(); 470 + } 471 + 472 + for (value, 0..) |val, idx| { 473 + indent( 474 + next_ctx, 475 + next_ctx.options.inline_slice, 476 + run, 477 + ); 478 + 479 + run.setColor(ctx, .dim); 480 + if (idx != 0 and ctx.options.inline_slice) 481 + try run.write(", "); 482 + 483 + if (!ctx.options.inline_slice or ctx.options.always_show_index) { 484 + try run.write(ctx.options.theme.index_open); 485 + try run.print("{}", .{idx}); 486 + try run.write(ctx.options.theme.index_close ++ 487 + ctx.options.theme.index_value_sep); 488 + } 489 + 490 + run.resetColor(); 491 + 492 + try innerFmt(ptr.child, next_ctx, run, val, .{ .skip_type_name = true }); 493 + } 494 + } 495 + 496 + inline fn formatPtrMany( 497 + comptime ctx: Context, 498 + comptime ptr: Type.Pointer, 499 + run: *Runtime, 500 + value: anytype, 501 + ) !void { 502 + _ = ptr; 503 + run.setColor(ctx, .dim); 504 + run.setColor(ctx, .many_ptr); 505 + try run.print("{*}", .{value}); 506 + run.resetColor(); 507 + } 508 + 509 + inline fn formatString( 510 + comptime ctx: Context, 511 + run: *Runtime, 512 + value: anytype, 513 + ) !void { 514 + run.setColor(ctx, .string); 515 + try run.write("\""); 516 + try run.write(value); 517 + try run.write("\""); 416 518 run.resetColor(); 417 519 } 418 520